2
0
mirror of https://github.com/9ParsonsB/Pulsar.git synced 2025-04-05 17:39:39 -04:00
pulsar/ObservatoryCore/PluginManagement/PluginEventHandler.cs
F K 38b950cf37
[Core] Spit and polish on PluginList and tabs (#138)
Add checkboxes to the PluginList which allow you to enable/disable each plugin on-the-fly (it will no longer respond to events, but you can still configure it, etc.). These settings are preserved in a new Core setting. Also enabled full-row select for easier selection in the listview.

Also increased the height of the PluginList slightly. (Personally, I'd like it even taller.)

Also made slight sizing adjustments to the plugin tabs, which now show 3 letters when collapsed and has a bit of extra space so the longest one does not get cut-off when selected/bolded. Furthermore, the list of plugins is now sorted alphabetically.

Finally, set the plugin listview Dock = Fill (vs. Anchored). This seems to have fixed the listview resize problem I was experiencing.
2024-01-29 15:37:31 -05:00

198 lines
6.5 KiB
C#

using Observatory.Framework;
using Observatory.Framework.Interfaces;
using Observatory.Framework.Files;
using System;
using System.Collections.Generic;
using System.Linq;
using Observatory.Framework.Files.Journal;
using System.Timers;
using Observatory.Utils;
using Observatory.Framework.Files.ParameterTypes;
namespace Observatory.PluginManagement
{
class PluginEventHandler
{
private IEnumerable<IObservatoryWorker> observatoryWorkers;
private IEnumerable<IObservatoryNotifier> observatoryNotifiers;
private HashSet<IObservatoryPlugin> disabledPlugins;
private List<(string error, string detail)> errorList;
private System.Timers.Timer timer;
public PluginEventHandler(IEnumerable<IObservatoryWorker> observatoryWorkers, IEnumerable<IObservatoryNotifier> observatoryNotifiers)
{
this.observatoryWorkers = observatoryWorkers;
this.observatoryNotifiers = observatoryNotifiers;
disabledPlugins = new();
errorList = new();
InitializeTimer();
}
private void InitializeTimer()
{
// Use a timer to delay error reporting until incoming errors are "quiet" for one full second.
// Should resolve issue where repeated plugin errors open hundreds of error windows.
timer = new();
timer.Interval = 1000;
timer.Elapsed += ReportErrorsIfAny;
}
public void OnJournalEvent(object source, JournalEventArgs journalEventArgs)
{
foreach (var worker in observatoryWorkers)
{
if (disabledPlugins.Contains(worker)) continue;
try
{
worker.JournalEvent((JournalBase)journalEventArgs.journalEvent);
}
catch (PluginException ex)
{
RecordError(ex);
}
catch (Exception ex)
{
RecordError(ex, worker.Name, journalEventArgs.journalType.Name, ((JournalBase)journalEventArgs.journalEvent).Json);
}
ResetTimer();
}
}
public void OnStatusUpdate(object sourece, JournalEventArgs journalEventArgs)
{
foreach (var worker in observatoryWorkers)
{
if (disabledPlugins.Contains(worker)) continue;
try
{
worker.StatusChange((Status)journalEventArgs.journalEvent);
}
catch (PluginException ex)
{
RecordError(ex);
}
catch (Exception ex)
{
RecordError(ex, worker.Name, journalEventArgs.journalType.Name, ((JournalBase)journalEventArgs.journalEvent).Json);
}
ResetTimer();
}
}
internal void OnLogMonitorStateChanged(object sender, LogMonitorStateChangedEventArgs e)
{
foreach (var worker in observatoryWorkers)
{
if (disabledPlugins.Contains(worker)) continue;
try
{
worker.LogMonitorStateChanged(e);
}
catch (Exception ex)
{
RecordError(ex, worker.Name, "LogMonitorStateChanged event", ex.StackTrace ?? "");
}
}
}
public void OnNotificationEvent(object source, NotificationArgs notificationArgs)
{
foreach (var notifier in observatoryNotifiers)
{
if (disabledPlugins.Contains(notifier)) continue;
try
{
notifier.OnNotificationEvent(notificationArgs);
}
catch (PluginException ex)
{
RecordError(ex);
}
catch (Exception ex)
{
RecordError(ex, notifier.Name, notificationArgs.Title, notificationArgs.Detail);
}
ResetTimer();
}
}
public void OnPluginMessageEvent(object _, PluginMessageArgs messageArgs)
{
foreach (var plugin in observatoryNotifiers.Cast<IObservatoryPlugin>().Concat(observatoryWorkers))
{
if (disabledPlugins.Contains(plugin)) continue;
try
{
plugin.HandlePluginMessage(messageArgs.SourceName, messageArgs.SourceVersion, messageArgs.Message);
}
catch (PluginException ex)
{
RecordError(ex);
}
catch(Exception ex)
{
RecordError(ex, plugin.Name, "OnPluginMessageEvent event", "");
}
}
}
public void SetPluginEnabled(IObservatoryPlugin plugin, bool enabled)
{
if (enabled) disabledPlugins.Remove(plugin);
else disabledPlugins.Add(plugin);
}
private void ResetTimer()
{
timer.Stop();
try
{
timer.Start();
}
catch
{
// Not sure why this happens, but I've reproduced it twice in a row after hitting
// read-all while also playing (ie. generating journals).
InitializeTimer();
timer.Start();
}
}
private void RecordError(PluginException ex)
{
errorList.Add(($"Error in {ex.PluginName}: {ex.Message}", ex.StackTrace ?? ""));
}
private void RecordError(Exception ex, string plugin, string eventType, string eventDetail)
{
errorList.Add(($"Error in {plugin} while handling {eventType}: {ex.Message}", eventDetail));
}
private void ReportErrorsIfAny(object sender, ElapsedEventArgs e)
{
if (errorList.Any())
{
ErrorReporter.ShowErrorPopup($"Plugin Error{(errorList.Count > 1 ? "s" : "")}", errorList);
timer.Stop();
}
}
}
internal class PluginMessageArgs
{
internal string SourceName;
internal string SourceVersion;
internal object Message;
internal PluginMessageArgs(string sourceName, string sourceVersion, object message)
{
SourceName = sourceName;
SourceVersion = sourceVersion;
Message = message;
}
}
}