Plugin info - Implemented property changed

Plugins - Improved enable failure detection
Plugins UI - Show an indicator on plugins that failed to enable
Plugins UI - Show a progress indicator on plugins that are enabling
UI - Added reusable Snackbar (not the Dutch kind with kroketten)
This commit is contained in:
Robert committed 2020-06-25 19:25:58 +02:00
1 parent 28bcfcc95a
commit a47eedf1c2
18 files changed
+399 -179

No files matched your search

@@ -66,8 +66,9 @@
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="1.5*" />
</Grid.ColumnDefinitions>
<!-- Left side -->
@@ -157,8 +158,11 @@
</materialDesign:DialogHost>
</Grid>
<!-- Resize -->
<GridSplitter Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" Width="15" HorizontalAlignment="Stretch" Cursor="SizeWE" Margin="-15 0" Background="Transparent" />
<!-- Right side -->
<Grid Grid.Row="0" Grid.Column="1">
<Grid Grid.Row="0" Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="56" />
<RowDefinition Height="*" />
@@ -214,72 +218,124 @@
<!-- Bottom row, a bit hacky but has a ZIndex of 2 to cut off the time caret that overlaps the entire timeline -->
<Grid Grid.Row="1"
Grid.ColumnSpan="2"
Grid.Column="0"
HorizontalAlignment="Stretch"
Panel.ZIndex="2"
Background="{DynamicResource MaterialDesignCardBackground}">
<!-- Selected layer controls -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0"
Orientation="Horizontal"
Margin="6"
Visibility="{Binding SelectedLayer, Converter={StaticResource NullToVisibilityConverter}}">
<materialDesign:PackIcon Kind="Layers" Width="16" />
<materialDesign:PackIcon Kind="{Binding SelectedLayer.LayerBrush.Descriptor.Icon}"
Width="16"
Margin="5 0 0 0"
ToolTip="{Binding SelectedLayer.LayerBrush.Descriptor.DisplayName, Mode=OneWay}"
Background="Transparent"
Visibility="{Binding SelectedLayer.LayerBrush, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock Text="{Binding SelectedLayer.Name}" Margin="5 0 0 0" />
</StackPanel>
<StackPanel Grid.Column="0"
Orientation="Horizontal"
Margin="6"
Visibility="{Binding SelectedFolder, Converter={StaticResource NullToVisibilityConverter}}">
<materialDesign:PackIcon Kind="Folder" Width="16" />
<TextBlock Text="{Binding SelectedFolder.Name}" Margin="5 0 0 0" />
</StackPanel>
<Button Grid.Column="1"
Style="{StaticResource MaterialDesignFlatMidBgButton}"
Margin="0 -2"
Padding="10 0"
Height="20"
Width="110"
ToolTip="Select an effect to add"
VerticalAlignment="Center"
Visibility="{Binding PropertyTreeVisible, Converter={x:Static s:BoolToVisibilityConverter.Instance}}"
Command="{x:Static materialDesign:Transitioner.MoveLastCommand}"
CommandTarget="{Binding ElementName=TransitionCommandAnchor}">
<TextBlock FontSize="10">
ADD EFFECT
</TextBlock>
</Button>
<Button Grid.Column="1"
Style="{StaticResource MaterialDesignFlatMidBgButton}"
Margin="0 -2"
Padding="10 0"
Height="20"
Width="110"
ToolTip="Show the layer/folder properties"
VerticalAlignment="Center"
Visibility="{Binding PropertyTreeVisible, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}}"
Command="{x:Static materialDesign:Transitioner.MoveFirstCommand}"
CommandTarget="{Binding ElementName=TransitionCommandAnchor}">
<TextBlock FontSize="10">
SHOW PROPERTIES
</TextBlock>
</Button>
</Grid>
<StackPanel Grid.Column="0"
Orientation="Horizontal"
Margin="6"
Visibility="{Binding SelectedLayer, Converter={StaticResource NullToVisibilityConverter}}">
<materialDesign:PackIcon Kind="Layers" Width="16" />
<materialDesign:PackIcon Kind="{Binding SelectedLayer.LayerBrush.Descriptor.Icon}"
Width="16"
Margin="5 0 0 0"
ToolTip="{Binding SelectedLayer.LayerBrush.Descriptor.DisplayName, Mode=OneWay}"
Background="Transparent"
Visibility="{Binding SelectedLayer.LayerBrush, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock Text="{Binding SelectedLayer.Name}" Margin="5 0 0 0" />
</StackPanel>
<StackPanel Grid.Column="0"
Orientation="Horizontal"
Margin="6"
Visibility="{Binding SelectedFolder, Converter={StaticResource NullToVisibilityConverter}}">
<materialDesign:PackIcon Kind="Folder" Width="16" />
<TextBlock Text="{Binding SelectedFolder.Name}" Margin="5 0 0 0" />
</StackPanel>
<Button Grid.Column="1"
Style="{StaticResource MaterialDesignFlatMidBgButton}"
Margin="0 -2 5 -2"
Padding="10 0"
Height="20"
Width="110"
ToolTip="Select an effect to add"
VerticalAlignment="Center"
Visibility="{Binding PropertyTreeVisible, Converter={x:Static s:BoolToVisibilityConverter.Instance}}"
Command="{x:Static materialDesign:Transitioner.MoveLastCommand}"
CommandTarget="{Binding ElementName=TransitionCommandAnchor}">
<TextBlock FontSize="11">
ADD EFFECT
</TextBlock>
</Button>
<Button Grid.Column="1"
Style="{StaticResource MaterialDesignFlatMidBgButton}"
Margin="0 -2 5 -2"
Padding="10 0"
Height="20"
Width="110"
ToolTip="Show the layer/folder properties"
VerticalAlignment="Center"
Visibility="{Binding PropertyTreeVisible, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}}"
Command="{x:Static materialDesign:Transitioner.MoveFirstCommand}"
CommandTarget="{Binding ElementName=TransitionCommandAnchor}">
<TextBlock FontSize="11">
SHOW PROPERTIES
</TextBlock>
</Button>
</Grid>
<Grid Grid.Row="1"
Grid.Column="2"
HorizontalAlignment="Stretch"
Panel.ZIndex="2"
Background="{DynamicResource MaterialDesignCardBackground}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ListBox Style="{StaticResource MaterialDesignToolToggleListBox}" SelectedIndex="0" Height="20" Margin="5 0 0 0">
<ListBoxItem Padding="10 0">
<ListBoxItem.ToolTip>
<ToolTip Placement="Top" VerticalOffset="-5">
<StackPanel>
<TextBlock>Select the <Run FontWeight="Bold">enter</Run> timeline</TextBlock>
<TextBlock>Played when the folder/layer starts displaying (condition is met)</TextBlock>
</StackPanel>
</ToolTip>
</ListBoxItem.ToolTip>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="RayStart" Width="20" Height="20" Margin="0 -4" />
<TextBlock Margin="5 0 0 0" FontSize="11">ENTER</TextBlock>
</StackPanel>
</ListBoxItem>
<ListBoxItem Padding="10 0">
<ListBoxItem.ToolTip>
<ToolTip Placement="Top" VerticalOffset="-5">
<StackPanel>
<TextBlock>Select the <Run FontWeight="Bold">main</Run> timeline</TextBlock>
<TextBlock>Played after the enter timeline finishes, either on repeat or once</TextBlock>
</StackPanel>
</ToolTip>
</ListBoxItem.ToolTip>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="RayStartEnd" Width="20" Height="20" Margin="0 -4" />
<TextBlock Margin="5 0 0 0" FontSize="11">MAIN</TextBlock>
</StackPanel>
</ListBoxItem>
<ListBoxItem Padding="10 0">
<ListBoxItem.ToolTip>
<ToolTip Placement="Top" VerticalOffset="-5">
<StackPanel>
<TextBlock>Select the <Run FontWeight="Bold">exit</Run> timeline</TextBlock>
<TextBlock>Played when the folder/layer stops displaying (conditon no longer met)</TextBlock>
</StackPanel>
</ToolTip>
</ListBoxItem.ToolTip>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="RayEnd" Width="20" Height="20" Margin="0 -4" />
<TextBlock Margin="5 0 0 0" FontSize="11">EXIT</TextBlock>
</StackPanel>
</ListBoxItem>
</ListBox>
<!-- Zoom control -->
<Slider Grid.Column="1"
@@ -290,6 +346,7 @@
Maximum="350"
Value="{Binding ProfileEditorService.PixelsPerSecond}"
Width="319" />
</Grid>
</Grid>
</UserControl>
+25 -22
View File
@@ -47,27 +47,30 @@
</Style.Triggers>
</Style>
</mde:MaterialWindow.Resources>
<materialDesign:DialogHost Identifier="RootDialog" DialogTheme="Inherit">
<materialDesign:DrawerHost IsLeftDrawerOpen="{Binding IsSidebarVisible}">
<materialDesign:DrawerHost.LeftDrawerContent>
<ContentControl s:View.Model="{Binding SidebarViewModel}" Width="220" ClipToBounds="False" />
</materialDesign:DrawerHost.LeftDrawerContent>
<DockPanel>
<mde:AppBar Type="Dense"
IsNavigationDrawerOpen="{Binding IsSidebarVisible, Mode=TwoWay}"
Title="{Binding ActiveItem.DisplayName}"
ShowNavigationDrawerButton="True"
DockPanel.Dock="Top">
<StackPanel>
<!-- Bug: materialDesign:RippleAssist.RippleOnTop doesn't look as nice but otherwise it doesn't work at all, not sure why -->
<Button Style="{StaticResource MaterialDesignIconForegroundButton}" ToolTip="Open debugger" Command="{s:Action ShowDebugger}"
materialDesign:RippleAssist.RippleOnTop="True">
<materialDesign:PackIcon Kind="Matrix" />
</Button>
</StackPanel>
</mde:AppBar>
<ContentControl s:View.Model="{Binding ActiveItem}" Style="{StaticResource InitializingFade}" />
</DockPanel>
</materialDesign:DrawerHost>
<materialDesign:DialogHost Identifier="RootDialog" DialogTheme="Inherit" SnackbarMessageQueue="{Binding MainMessageQueue}">
<Grid>
<materialDesign:DrawerHost IsLeftDrawerOpen="{Binding IsSidebarVisible}">
<materialDesign:DrawerHost.LeftDrawerContent>
<ContentControl s:View.Model="{Binding SidebarViewModel}" Width="220" ClipToBounds="False" />
</materialDesign:DrawerHost.LeftDrawerContent>
<DockPanel>
<mde:AppBar Type="Dense"
IsNavigationDrawerOpen="{Binding IsSidebarVisible, Mode=TwoWay}"
Title="{Binding ActiveItem.DisplayName}"
ShowNavigationDrawerButton="True"
DockPanel.Dock="Top">
<StackPanel>
<!-- Bug: materialDesign:RippleAssist.RippleOnTop doesn't look as nice but otherwise it doesn't work at all, not sure why -->
<Button Style="{StaticResource MaterialDesignIconForegroundButton}" ToolTip="Open debugger" Command="{s:Action ShowDebugger}"
materialDesign:RippleAssist.RippleOnTop="True">
<materialDesign:PackIcon Kind="Matrix" />
</Button>
</StackPanel>
</mde:AppBar>
<ContentControl s:View.Model="{Binding ActiveItem}" Style="{StaticResource InitializingFade}" />
</DockPanel>
</materialDesign:DrawerHost>
<materialDesign:Snackbar x:Name="MainSnackbar" MessageQueue="{Binding MainMessageQueue}" />
</Grid>
</materialDesign:DialogHost>
</mde:MaterialWindow>
+5 -4
View File
@@ -27,10 +27,11 @@ namespace Artemis.UI.Screens
private readonly Timer _titleUpdateTimer;
private bool _lostFocus;
public RootViewModel(IEventAggregator eventAggregator, SidebarViewModel sidebarViewModel, ISettingsService settingsService, ICoreService coreService,
IDebugService debugService)
public RootViewModel(IEventAggregator eventAggregator, SidebarViewModel sidebarViewModel, ISettingsService settingsService, ICoreService coreService,
IDebugService debugService, ISnackbarMessageQueue snackbarMessageQueue)
{
SidebarViewModel = sidebarViewModel;
MainMessageQueue = snackbarMessageQueue;
_eventAggregator = eventAggregator;
_coreService = coreService;
_debugService = debugService;
@@ -49,11 +50,11 @@ namespace Artemis.UI.Screens
}
public SidebarViewModel SidebarViewModel { get; }
public ISnackbarMessageQueue MainMessageQueue { get; set; }
public bool IsSidebarVisible { get; set; }
public bool ActiveItemReady { get; set; }
public string WindowTitle { get; set; }
public void WindowDeactivated()
{
var windowState = ((Window) View).WindowState;
@@ -27,20 +27,20 @@ namespace Artemis.UI.Screens.Settings
private readonly IDialogService _dialogService;
private readonly IPluginService _pluginService;
private readonly ISettingsService _settingsService;
private readonly IPluginSettingsVmFactory _pluginSettingsVmFactory;
private readonly ISurfaceService _surfaceService;
private readonly IWindowManager _windowManager;
public SettingsViewModel(ISurfaceService surfaceService, IPluginService pluginService, IDialogService dialogService, IWindowManager windowManager,
IDebugService debugService, ISettingsService settingsService, IDeviceSettingsVmFactory deviceSettingsVmFactory)
public SettingsViewModel(ISurfaceService surfaceService, IPluginService pluginService, IDialogService dialogService, IDebugService debugService,
ISettingsService settingsService, IPluginSettingsVmFactory pluginSettingsVmFactory, IDeviceSettingsVmFactory deviceSettingsVmFactory)
{
DisplayName = "Settings";
_surfaceService = surfaceService;
_pluginService = pluginService;
_dialogService = dialogService;
_windowManager = windowManager;
_debugService = debugService;
_settingsService = settingsService;
_pluginSettingsVmFactory = pluginSettingsVmFactory;
_deviceSettingsVmFactory = deviceSettingsVmFactory;
DeviceSettingsViewModels = new BindableCollection<DeviceSettingsViewModel>();
@@ -189,7 +189,7 @@ namespace Artemis.UI.Screens.Settings
DeviceSettingsViewModels.AddRange(_surfaceService.ActiveSurface.Devices.Select(d => _deviceSettingsVmFactory.Create(d)));
Plugins.Clear();
Plugins.AddRange(_pluginService.GetAllPluginInfo().Select(p => new PluginSettingsViewModel(p.Instance, _windowManager, _dialogService, _pluginService)));
Plugins.AddRange(_pluginService.GetAllPluginInfo().Select(p => _pluginSettingsVmFactory.Create(p.Instance)));
base.OnInitialActivate();
}
@@ -36,6 +36,7 @@
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
@@ -43,9 +44,16 @@
</Grid.RowDefinitions>
<materialDesign:PackIcon Kind="{Binding Icon}" Width="48" Height="48" Grid.Row="0" Grid.RowSpan="2" HorizontalAlignment="Center" />
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Text="{Binding PluginInfo.Name}" Grid.Column="1" Grid.Row="0" />
<TextBlock Grid.Column="1" Grid.Row="0" Style="{StaticResource MaterialDesignTextBlock}" Text="{Binding PluginInfo.Name}" />
<materialDesign:Card Grid.Column="2" Grid.Row="0" Background="#FF4343" Height="22" Padding="4" Margin="0 -18 0 0"
Visibility="{Binding PluginInfo.LastEnableSuccessful, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}">
LOAD FAILED
</materialDesign:Card>
<TextBlock Grid.Column="1"
Grid.Row="1"
Grid.ColumnSpan="2"
TextWrapping="Wrap"
Text="{Binding PluginInfo.Description}"
Style="{StaticResource MaterialDesignTextBlock}"
@@ -56,15 +64,17 @@
<Button Style="{StaticResource MaterialDesignOutlinedButton}" ToolTip="MaterialDesignOutlinedButton" Margin="4" s:View.ActionTarget="{Binding}" Command="{s:Action OpenSettings}">
SETTINGS
</Button>
<!-- <Button Style="{StaticResource MaterialDesignOutlinedButton}" ToolTip="MaterialDesignOutlinedButton" Margin="4"> -->
<!-- SETTINGS -->
<!-- </Button> -->
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="8">
<StackPanel Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="8"
Visibility="{Binding Enabling, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}">
<CheckBox Style="{StaticResource MaterialDesignCheckBox}" IsChecked="{Binding IsEnabled}">
Plugin enabled
</CheckBox>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="8"
Visibility="{Binding Enabling, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}" Value="0" IsIndeterminate="True" />
</StackPanel>
</Grid>
</materialDesign:Card>
</UserControl>
@@ -1,4 +1,6 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.Models;
@@ -13,9 +15,11 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
{
private readonly IDialogService _dialogService;
private readonly IPluginService _pluginService;
private readonly ISnackbarMessageQueue _snackbarMessageQueue;
private readonly IWindowManager _windowManager;
public PluginSettingsViewModel(Plugin plugin, IWindowManager windowManager, IDialogService dialogService, IPluginService pluginService)
public PluginSettingsViewModel(Plugin plugin, IWindowManager windowManager, IDialogService dialogService, IPluginService pluginService,
ISnackbarMessageQueue snackbarMessageQueue)
{
Plugin = plugin;
PluginInfo = plugin.PluginInfo;
@@ -23,6 +27,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
_windowManager = windowManager;
_dialogService = dialogService;
_pluginService = pluginService;
_snackbarMessageQueue = snackbarMessageQueue;
}
public Plugin Plugin { get; set; }
@@ -40,6 +45,8 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
public bool CanOpenSettings => IsEnabled && Plugin.HasConfigurationViewModel;
public bool Enabling { get; set; }
public async Task OpenSettings()
{
try
@@ -55,6 +62,18 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
}
}
public async Task ShowLogsFolder()
{
try
{
Process.Start(Environment.GetEnvironmentVariable("WINDIR") + @"\explorer.exe", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"));
}
catch (Exception e)
{
await _dialogService.ShowExceptionDialog("Welp, we couldn\'t open the logs folder for you", e);
}
}
private PackIconKind GetIconKind()
{
if (PluginInfo.Icon != null)
@@ -105,7 +124,23 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
}
if (enable)
_pluginService.EnablePlugin(Plugin);
{
Enabling = true;
try
{
_pluginService.EnablePlugin(Plugin);
_snackbarMessageQueue.Enqueue($"Enabled plugin {PluginInfo.Name}");
}
catch (Exception)
{
_snackbarMessageQueue.Enqueue($"Failed to enable plugin {PluginInfo.Name}", "VIEW LOGS", async () => await ShowLogsFolder());
}
finally
{
Enabling = false;
NotifyOfPropertyChange(() => IsEnabled);
}
}
else
_pluginService.DisablePlugin(Plugin);