mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-22 00:54:26 +08:00
settings_re8
This commit is contained in:
@@ -0,0 +1,365 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Avalonia.Controls;
|
||||
using LanMountainDesktop.ComponentSystem;
|
||||
using LanMountainDesktop.Models;
|
||||
using LanMountainDesktop.Plugins;
|
||||
using LanMountainDesktop.PluginSdk;
|
||||
using LanMountainDesktop.Views.ComponentEditors;
|
||||
|
||||
namespace LanMountainDesktop.Services;
|
||||
|
||||
public static class DesktopComponentEditorRegistryFactory
|
||||
{
|
||||
public static DesktopComponentEditorRegistry Create(
|
||||
ComponentRegistry componentRegistry,
|
||||
PluginRuntimeService? pluginRuntimeService)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(componentRegistry);
|
||||
|
||||
var registrations = GetBuiltInRegistrations(componentRegistry).ToList();
|
||||
var registeredIds = new HashSet<string>(
|
||||
registrations.Select(registration => registration.ComponentId),
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (pluginRuntimeService is not null)
|
||||
{
|
||||
foreach (var contribution in pluginRuntimeService.DesktopComponentEditors)
|
||||
{
|
||||
var registration = contribution.Registration;
|
||||
if (!componentRegistry.TryGetDefinition(registration.ComponentId, out var definition) ||
|
||||
!definition.AllowDesktopPlacement ||
|
||||
!registeredIds.Add(registration.ComponentId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
registrations.Add(new DesktopComponentEditorRegistration(
|
||||
registration.ComponentId,
|
||||
context => CreatePluginEditor(contribution, context),
|
||||
registration.PreferredWidth,
|
||||
registration.PreferredHeight,
|
||||
registration.MinScale,
|
||||
registration.MaxScale));
|
||||
}
|
||||
}
|
||||
|
||||
return new DesktopComponentEditorRegistry(componentRegistry, registrations);
|
||||
}
|
||||
|
||||
private static IEnumerable<DesktopComponentEditorRegistration> GetBuiltInRegistrations(ComponentRegistry componentRegistry)
|
||||
{
|
||||
var registrations = new Dictionary<string, DesktopComponentEditorRegistration>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
[BuiltInComponentIds.DesktopClock] = new(
|
||||
BuiltInComponentIds.DesktopClock,
|
||||
context => new ClockComponentEditor(context)),
|
||||
[BuiltInComponentIds.DesktopWorldClock] = new(
|
||||
BuiltInComponentIds.DesktopWorldClock,
|
||||
context => new WorldClockComponentEditor(context),
|
||||
preferredWidth: 820d,
|
||||
preferredHeight: 620d),
|
||||
[BuiltInComponentIds.DesktopClassSchedule] = new(
|
||||
BuiltInComponentIds.DesktopClassSchedule,
|
||||
context => new ClassScheduleComponentEditor(context),
|
||||
preferredWidth: 860d,
|
||||
preferredHeight: 640d),
|
||||
[BuiltInComponentIds.DesktopDailyArtwork] = new(
|
||||
BuiltInComponentIds.DesktopDailyArtwork,
|
||||
context => new DailyArtworkComponentEditor(context)),
|
||||
[BuiltInComponentIds.DesktopStudyEnvironment] = new(
|
||||
BuiltInComponentIds.DesktopStudyEnvironment,
|
||||
context => new StudyEnvironmentComponentEditor(context)),
|
||||
[BuiltInComponentIds.DesktopWeather] = CreateWeatherRegistration(BuiltInComponentIds.DesktopWeather),
|
||||
[BuiltInComponentIds.DesktopWeatherClock] = CreateWeatherRegistration(BuiltInComponentIds.DesktopWeatherClock),
|
||||
[BuiltInComponentIds.DesktopHourlyWeather] = CreateWeatherRegistration(BuiltInComponentIds.DesktopHourlyWeather),
|
||||
[BuiltInComponentIds.DesktopMultiDayWeather] = CreateWeatherRegistration(BuiltInComponentIds.DesktopMultiDayWeather),
|
||||
[BuiltInComponentIds.DesktopExtendedWeather] = CreateWeatherRegistration(BuiltInComponentIds.DesktopExtendedWeather),
|
||||
[BuiltInComponentIds.DesktopCnrDailyNews] = new(
|
||||
BuiltInComponentIds.DesktopCnrDailyNews,
|
||||
context => new ToggleIntervalComponentEditor(
|
||||
context,
|
||||
new ToggleIntervalComponentEditorOptions
|
||||
{
|
||||
DescriptionKey = "cnr.settings.desc",
|
||||
DescriptionFallback = "Configure auto rotation for this CNR news widget.",
|
||||
ToggleLabelKey = "cnr.settings.auto_rotate",
|
||||
ToggleLabelFallback = "Auto rotate",
|
||||
ToggleDescriptionKey = "component.editor.instance_scope",
|
||||
ToggleDescriptionFallback = "Changes are stored per component instance.",
|
||||
IntervalLabelKey = "cnr.settings.rotate_interval",
|
||||
IntervalLabelFallback = "Rotate interval",
|
||||
DefaultInterval = 60,
|
||||
GetEnabled = snapshot => snapshot.CnrDailyNewsAutoRotateEnabled,
|
||||
SetEnabled = (snapshot, value) => snapshot.CnrDailyNewsAutoRotateEnabled = value,
|
||||
GetInterval = snapshot => snapshot.CnrDailyNewsAutoRotateIntervalMinutes,
|
||||
SetInterval = (snapshot, value) => snapshot.CnrDailyNewsAutoRotateIntervalMinutes = value,
|
||||
ChangedKeys =
|
||||
[
|
||||
nameof(ComponentSettingsSnapshot.CnrDailyNewsAutoRotateEnabled),
|
||||
nameof(ComponentSettingsSnapshot.CnrDailyNewsAutoRotateIntervalMinutes)
|
||||
]
|
||||
})),
|
||||
[BuiltInComponentIds.DesktopIfengNews] = new(
|
||||
BuiltInComponentIds.DesktopIfengNews,
|
||||
context => new ToggleIntervalComponentEditor(
|
||||
context,
|
||||
new ToggleIntervalComponentEditorOptions
|
||||
{
|
||||
DescriptionKey = "ifeng.settings.desc",
|
||||
DescriptionFallback = "Configure auto refresh and source channel for this iFeng widget.",
|
||||
ToggleLabelKey = "ifeng.settings.auto_refresh",
|
||||
ToggleLabelFallback = "Auto refresh",
|
||||
ToggleDescriptionKey = "component.editor.instance_scope",
|
||||
ToggleDescriptionFallback = "Changes are stored per component instance.",
|
||||
IntervalLabelKey = "ifeng.settings.refresh_interval",
|
||||
IntervalLabelFallback = "Refresh interval",
|
||||
DefaultInterval = 20,
|
||||
GetEnabled = snapshot => snapshot.IfengNewsAutoRefreshEnabled,
|
||||
SetEnabled = (snapshot, value) => snapshot.IfengNewsAutoRefreshEnabled = value,
|
||||
GetInterval = snapshot => snapshot.IfengNewsAutoRefreshIntervalMinutes,
|
||||
SetInterval = (snapshot, value) => snapshot.IfengNewsAutoRefreshIntervalMinutes = value,
|
||||
ExtraSelectorLabelKey = "ifeng.settings.channel",
|
||||
ExtraSelectorLabelFallback = "Channel",
|
||||
ExtraOptions =
|
||||
[
|
||||
new ComponentEditorSelectionOption(
|
||||
IfengNewsChannelTypes.Comprehensive,
|
||||
"ifeng.settings.channel.comprehensive",
|
||||
"Comprehensive"),
|
||||
new ComponentEditorSelectionOption(
|
||||
IfengNewsChannelTypes.Mainland,
|
||||
"ifeng.settings.channel.mainland",
|
||||
"Mainland"),
|
||||
new ComponentEditorSelectionOption(
|
||||
IfengNewsChannelTypes.Taiwan,
|
||||
"ifeng.settings.channel.taiwan",
|
||||
"Taiwan")
|
||||
],
|
||||
GetExtraValue = snapshot => IfengNewsChannelTypes.Normalize(snapshot.IfengNewsChannelType),
|
||||
SetExtraValue = (snapshot, value) => snapshot.IfengNewsChannelType = IfengNewsChannelTypes.Normalize(value),
|
||||
ChangedKeys =
|
||||
[
|
||||
nameof(ComponentSettingsSnapshot.IfengNewsAutoRefreshEnabled),
|
||||
nameof(ComponentSettingsSnapshot.IfengNewsAutoRefreshIntervalMinutes),
|
||||
nameof(ComponentSettingsSnapshot.IfengNewsChannelType)
|
||||
]
|
||||
})),
|
||||
[BuiltInComponentIds.DesktopDailyWord] = CreateDailyWordRegistration(BuiltInComponentIds.DesktopDailyWord),
|
||||
[BuiltInComponentIds.DesktopDailyWord2x2] = CreateDailyWordRegistration(BuiltInComponentIds.DesktopDailyWord2x2),
|
||||
[BuiltInComponentIds.DesktopBilibiliHotSearch] = new(
|
||||
BuiltInComponentIds.DesktopBilibiliHotSearch,
|
||||
context => new ToggleIntervalComponentEditor(
|
||||
context,
|
||||
new ToggleIntervalComponentEditorOptions
|
||||
{
|
||||
DescriptionKey = "bilibili.settings.desc",
|
||||
DescriptionFallback = "Configure auto refresh for this Bilibili hot search widget.",
|
||||
ToggleLabelKey = "bilibili.settings.auto_refresh",
|
||||
ToggleLabelFallback = "Auto refresh",
|
||||
ToggleDescriptionKey = "component.editor.instance_scope",
|
||||
ToggleDescriptionFallback = "Changes are stored per component instance.",
|
||||
IntervalLabelKey = "bilibili.settings.refresh_interval",
|
||||
IntervalLabelFallback = "Refresh interval",
|
||||
DefaultInterval = 15,
|
||||
GetEnabled = snapshot => snapshot.BilibiliHotSearchAutoRefreshEnabled,
|
||||
SetEnabled = (snapshot, value) => snapshot.BilibiliHotSearchAutoRefreshEnabled = value,
|
||||
GetInterval = snapshot => snapshot.BilibiliHotSearchAutoRefreshIntervalMinutes,
|
||||
SetInterval = (snapshot, value) => snapshot.BilibiliHotSearchAutoRefreshIntervalMinutes = value,
|
||||
ChangedKeys =
|
||||
[
|
||||
nameof(ComponentSettingsSnapshot.BilibiliHotSearchAutoRefreshEnabled),
|
||||
nameof(ComponentSettingsSnapshot.BilibiliHotSearchAutoRefreshIntervalMinutes)
|
||||
]
|
||||
})),
|
||||
[BuiltInComponentIds.DesktopBaiduHotSearch] = new(
|
||||
BuiltInComponentIds.DesktopBaiduHotSearch,
|
||||
context => new ToggleIntervalComponentEditor(
|
||||
context,
|
||||
new ToggleIntervalComponentEditorOptions
|
||||
{
|
||||
DescriptionKey = "baidu.settings.desc",
|
||||
DescriptionFallback = "Configure auto refresh and source for this Baidu hot search widget.",
|
||||
ToggleLabelKey = "baidu.settings.auto_refresh",
|
||||
ToggleLabelFallback = "Auto refresh",
|
||||
ToggleDescriptionKey = "component.editor.instance_scope",
|
||||
ToggleDescriptionFallback = "Changes are stored per component instance.",
|
||||
IntervalLabelKey = "baidu.settings.refresh_interval",
|
||||
IntervalLabelFallback = "Refresh interval",
|
||||
DefaultInterval = 15,
|
||||
GetEnabled = snapshot => snapshot.BaiduHotSearchAutoRefreshEnabled,
|
||||
SetEnabled = (snapshot, value) => snapshot.BaiduHotSearchAutoRefreshEnabled = value,
|
||||
GetInterval = snapshot => snapshot.BaiduHotSearchAutoRefreshIntervalMinutes,
|
||||
SetInterval = (snapshot, value) => snapshot.BaiduHotSearchAutoRefreshIntervalMinutes = value,
|
||||
ExtraSelectorLabelKey = "baidu.settings.source",
|
||||
ExtraSelectorLabelFallback = "Source",
|
||||
ExtraOptions =
|
||||
[
|
||||
new ComponentEditorSelectionOption(
|
||||
BaiduHotSearchSourceTypes.Official,
|
||||
"baidu.settings.source.official",
|
||||
"Official"),
|
||||
new ComponentEditorSelectionOption(
|
||||
BaiduHotSearchSourceTypes.ThirdPartyRss,
|
||||
"baidu.settings.source.third_party",
|
||||
"Third-party RSS")
|
||||
],
|
||||
GetExtraValue = snapshot => BaiduHotSearchSourceTypes.Normalize(snapshot.BaiduHotSearchSourceType),
|
||||
SetExtraValue = (snapshot, value) => snapshot.BaiduHotSearchSourceType = BaiduHotSearchSourceTypes.Normalize(value),
|
||||
ChangedKeys =
|
||||
[
|
||||
nameof(ComponentSettingsSnapshot.BaiduHotSearchAutoRefreshEnabled),
|
||||
nameof(ComponentSettingsSnapshot.BaiduHotSearchAutoRefreshIntervalMinutes),
|
||||
nameof(ComponentSettingsSnapshot.BaiduHotSearchSourceType)
|
||||
]
|
||||
})),
|
||||
[BuiltInComponentIds.DesktopStcn24Forum] = new(
|
||||
BuiltInComponentIds.DesktopStcn24Forum,
|
||||
context => new ToggleIntervalComponentEditor(
|
||||
context,
|
||||
new ToggleIntervalComponentEditorOptions
|
||||
{
|
||||
DescriptionKey = "stcn.settings.desc",
|
||||
DescriptionFallback = "Configure auto refresh and sort mode for this STCN forum widget.",
|
||||
ToggleLabelKey = "stcn.settings.auto_refresh",
|
||||
ToggleLabelFallback = "Auto refresh",
|
||||
ToggleDescriptionKey = "component.editor.instance_scope",
|
||||
ToggleDescriptionFallback = "Changes are stored per component instance.",
|
||||
IntervalLabelKey = "stcn.settings.refresh_interval",
|
||||
IntervalLabelFallback = "Refresh interval",
|
||||
DefaultInterval = 20,
|
||||
GetEnabled = snapshot => snapshot.Stcn24ForumAutoRefreshEnabled,
|
||||
SetEnabled = (snapshot, value) => snapshot.Stcn24ForumAutoRefreshEnabled = value,
|
||||
GetInterval = snapshot => snapshot.Stcn24ForumAutoRefreshIntervalMinutes,
|
||||
SetInterval = (snapshot, value) => snapshot.Stcn24ForumAutoRefreshIntervalMinutes = value,
|
||||
ExtraSelectorLabelKey = "stcn.settings.sort_mode",
|
||||
ExtraSelectorLabelFallback = "Sort mode",
|
||||
ExtraOptions = Stcn24ForumSourceTypes.SupportedValues
|
||||
.Select(value => new ComponentEditorSelectionOption(
|
||||
value,
|
||||
$"stcn.settings.source.{value}",
|
||||
value))
|
||||
.ToArray(),
|
||||
GetExtraValue = snapshot => Stcn24ForumSourceTypes.Normalize(snapshot.Stcn24ForumSourceType),
|
||||
SetExtraValue = (snapshot, value) => snapshot.Stcn24ForumSourceType = Stcn24ForumSourceTypes.Normalize(value),
|
||||
ChangedKeys =
|
||||
[
|
||||
nameof(ComponentSettingsSnapshot.Stcn24ForumAutoRefreshEnabled),
|
||||
nameof(ComponentSettingsSnapshot.Stcn24ForumAutoRefreshIntervalMinutes),
|
||||
nameof(ComponentSettingsSnapshot.Stcn24ForumSourceType)
|
||||
]
|
||||
}))
|
||||
};
|
||||
|
||||
foreach (var componentId in GetBuiltInDesktopComponentIds(componentRegistry))
|
||||
{
|
||||
if (registrations.ContainsKey(componentId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
registrations[componentId] = new DesktopComponentEditorRegistration(
|
||||
componentId,
|
||||
context => new InformationalComponentEditor(
|
||||
context,
|
||||
$"This {context.Definition.DisplayName} component currently exposes instance-scoped editor metadata only."));
|
||||
}
|
||||
|
||||
return registrations.Values;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetBuiltInDesktopComponentIds(ComponentRegistry componentRegistry)
|
||||
{
|
||||
return typeof(BuiltInComponentIds)
|
||||
.GetFields(BindingFlags.Public | BindingFlags.Static)
|
||||
.Where(field => field.FieldType == typeof(string))
|
||||
.Select(field => field.GetRawConstantValue() as string)
|
||||
.Where(id => !string.IsNullOrWhiteSpace(id))
|
||||
.Select(id => id!)
|
||||
.Where(id => componentRegistry.TryGetDefinition(id, out var definition) && definition.AllowDesktopPlacement)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static DesktopComponentEditorRegistration CreateWeatherRegistration(string componentId)
|
||||
{
|
||||
return new DesktopComponentEditorRegistration(
|
||||
componentId,
|
||||
context => new ToggleIntervalComponentEditor(
|
||||
context,
|
||||
new ToggleIntervalComponentEditorOptions
|
||||
{
|
||||
DescriptionKey = "weather.settings.desc",
|
||||
DescriptionFallback = "Configure weather auto refresh for this component instance.",
|
||||
ToggleLabelKey = "weather.settings.auto_refresh",
|
||||
ToggleLabelFallback = "Auto refresh",
|
||||
ToggleDescriptionKey = "component.editor.instance_scope",
|
||||
ToggleDescriptionFallback = "Changes are stored per component instance.",
|
||||
IntervalLabelKey = "weather.settings.refresh_interval",
|
||||
IntervalLabelFallback = "Refresh interval",
|
||||
DefaultInterval = 12,
|
||||
GetEnabled = snapshot => snapshot.WeatherAutoRefreshEnabled,
|
||||
SetEnabled = (snapshot, value) => snapshot.WeatherAutoRefreshEnabled = value,
|
||||
GetInterval = snapshot => snapshot.WeatherAutoRefreshIntervalMinutes,
|
||||
SetInterval = (snapshot, value) => snapshot.WeatherAutoRefreshIntervalMinutes = value,
|
||||
ChangedKeys =
|
||||
[
|
||||
nameof(ComponentSettingsSnapshot.WeatherAutoRefreshEnabled),
|
||||
nameof(ComponentSettingsSnapshot.WeatherAutoRefreshIntervalMinutes)
|
||||
]
|
||||
}));
|
||||
}
|
||||
|
||||
private static DesktopComponentEditorRegistration CreateDailyWordRegistration(string componentId)
|
||||
{
|
||||
return new DesktopComponentEditorRegistration(
|
||||
componentId,
|
||||
context => new ToggleIntervalComponentEditor(
|
||||
context,
|
||||
new ToggleIntervalComponentEditorOptions
|
||||
{
|
||||
DescriptionKey = "dailyword.settings.desc",
|
||||
DescriptionFallback = "Configure auto refresh for this Daily Word component.",
|
||||
ToggleLabelKey = "dailyword.settings.auto_refresh",
|
||||
ToggleLabelFallback = "Auto refresh",
|
||||
ToggleDescriptionKey = "component.editor.instance_scope",
|
||||
ToggleDescriptionFallback = "Changes are stored per component instance.",
|
||||
IntervalLabelKey = "dailyword.settings.refresh_interval",
|
||||
IntervalLabelFallback = "Refresh interval",
|
||||
DefaultInterval = 360,
|
||||
GetEnabled = snapshot => snapshot.DailyWordAutoRefreshEnabled,
|
||||
SetEnabled = (snapshot, value) => snapshot.DailyWordAutoRefreshEnabled = value,
|
||||
GetInterval = snapshot => snapshot.DailyWordAutoRefreshIntervalMinutes,
|
||||
SetInterval = (snapshot, value) => snapshot.DailyWordAutoRefreshIntervalMinutes = value,
|
||||
ChangedKeys =
|
||||
[
|
||||
nameof(ComponentSettingsSnapshot.DailyWordAutoRefreshEnabled),
|
||||
nameof(ComponentSettingsSnapshot.DailyWordAutoRefreshIntervalMinutes)
|
||||
]
|
||||
}));
|
||||
}
|
||||
|
||||
private static Control CreatePluginEditor(
|
||||
PluginDesktopComponentEditorContribution contribution,
|
||||
DesktopComponentEditorContext context)
|
||||
{
|
||||
var settingsService = contribution.Plugin.Services.GetService(typeof(ISettingsService)) as ISettingsService
|
||||
?? context.SettingsService;
|
||||
var pluginSettings = new PluginScopedSettingsService(
|
||||
contribution.Plugin.Manifest.Id,
|
||||
settingsService);
|
||||
var pluginContext = new PluginDesktopComponentEditorContext(
|
||||
contribution.Plugin.Manifest,
|
||||
contribution.Plugin.Context.PluginDirectory,
|
||||
contribution.Plugin.Context.DataDirectory,
|
||||
contribution.Plugin.Services,
|
||||
contribution.Plugin.Context.Properties,
|
||||
context.ComponentId,
|
||||
context.PlacementId,
|
||||
pluginSettings,
|
||||
context.HostContext);
|
||||
|
||||
return contribution.Registration.EditorFactory(contribution.Plugin.Services, pluginContext);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user