mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
0.6.7.2
文档组件优化
This commit is contained in:
@@ -64,6 +64,7 @@ public sealed class ComponentSettingsSnapshot
|
||||
|
||||
public string Stcn24ForumSourceType { get; set; } = Stcn24ForumSourceTypes.LatestCreated;
|
||||
|
||||
|
||||
public ComponentSettingsSnapshot Clone()
|
||||
{
|
||||
var clone = (ComponentSettingsSnapshot)MemberwiseClone();
|
||||
@@ -91,6 +92,9 @@ public sealed class ComponentSettingsSnapshot
|
||||
clone.WorldClockTimeZoneIds = WorldClockTimeZoneIds is { Count: > 0 }
|
||||
? new List<string>(WorldClockTimeZoneIds)
|
||||
: [];
|
||||
clone.OfficeRecentDocumentsEnabledSources = OfficeRecentDocumentsEnabledSources is not null
|
||||
? new List<string>(OfficeRecentDocumentsEnabledSources)
|
||||
: null;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
53
LanMountainDesktop/Models/OfficeRecentDocumentSourceTypes.cs
Normal file
53
LanMountainDesktop/Models/OfficeRecentDocumentSourceTypes.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace LanMountainDesktop.Models;
|
||||
|
||||
public static class OfficeRecentDocumentSourceTypes
|
||||
{
|
||||
public const string Registry = "registry";
|
||||
public const string RecentFolders = "recent_folders";
|
||||
public const string JumpLists = "jump_lists";
|
||||
|
||||
public static IReadOnlyList<string> SupportedValues { get; } =
|
||||
[
|
||||
Registry,
|
||||
RecentFolders,
|
||||
JumpLists
|
||||
];
|
||||
|
||||
public static IReadOnlyList<string> DefaultValues => SupportedValues;
|
||||
|
||||
public static IReadOnlyList<string> NormalizeValues(IEnumerable<string>? values, bool useDefaultWhenEmpty)
|
||||
{
|
||||
if (values is null)
|
||||
{
|
||||
return useDefaultWhenEmpty ? DefaultValues : Array.Empty<string>();
|
||||
}
|
||||
|
||||
var normalized = values
|
||||
.Select(NormalizeValue)
|
||||
.OfType<string>()
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray();
|
||||
|
||||
if (normalized.Length == 0 && useDefaultWhenEmpty)
|
||||
{
|
||||
return DefaultValues;
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private static string? NormalizeValue(string? value)
|
||||
{
|
||||
return value?.Trim().ToLowerInvariant() switch
|
||||
{
|
||||
Registry => Registry,
|
||||
RecentFolders => RecentFolders,
|
||||
JumpLists => JumpLists,
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,9 @@ public static class DesktopComponentEditorRegistryFactory
|
||||
[BuiltInComponentIds.DesktopRemovableStorage] = new(
|
||||
BuiltInComponentIds.DesktopRemovableStorage,
|
||||
context => new RemovableStorageComponentEditor(context)),
|
||||
[BuiltInComponentIds.DesktopOfficeRecentDocuments] = new(
|
||||
BuiltInComponentIds.DesktopOfficeRecentDocuments,
|
||||
context => new OfficeRecentDocumentsComponentEditor(context)),
|
||||
[BuiltInComponentIds.DesktopWeather] = CreateWeatherRegistration(BuiltInComponentIds.DesktopWeather),
|
||||
[BuiltInComponentIds.DesktopWeatherClock] = CreateWeatherRegistration(BuiltInComponentIds.DesktopWeatherClock),
|
||||
[BuiltInComponentIds.DesktopHourlyWeather] = CreateWeatherRegistration(BuiltInComponentIds.DesktopHourlyWeather),
|
||||
|
||||
@@ -9,6 +9,7 @@ using System.Runtime.Versioning;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using LanMountainDesktop.Models;
|
||||
using Microsoft.Win32;
|
||||
using MudTools.OfficeInterop;
|
||||
using MudTools.OfficeInterop.Excel;
|
||||
@@ -18,7 +19,7 @@ namespace LanMountainDesktop.Services;
|
||||
|
||||
public interface IOfficeRecentDocumentsService
|
||||
{
|
||||
List<OfficeRecentDocument> GetRecentDocuments(int maxCount = 20);
|
||||
List<OfficeRecentDocument> GetRecentDocuments(int maxCount = 20, IReadOnlyCollection<string>? enabledSources = null);
|
||||
void OpenDocument(string filePath);
|
||||
}
|
||||
|
||||
@@ -48,20 +49,38 @@ public sealed class OfficeRecentDocumentsService : IOfficeRecentDocumentsService
|
||||
@"\[T(?<filetime>[0-9A-F]+)\]",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
public List<OfficeRecentDocument> GetRecentDocuments(int maxCount = 20)
|
||||
public List<OfficeRecentDocument> GetRecentDocuments(int maxCount = 20, IReadOnlyCollection<string>? enabledSources = null)
|
||||
{
|
||||
var documents = new List<OfficeRecentDocument>();
|
||||
var normalizedSources = OfficeRecentDocumentSourceTypes.NormalizeValues(
|
||||
enabledSources,
|
||||
useDefaultWhenEmpty: enabledSources is null);
|
||||
|
||||
if (!OperatingSystem.IsWindows())
|
||||
if (!OperatingSystem.IsWindows() || normalizedSources.Count == 0)
|
||||
{
|
||||
return documents;
|
||||
}
|
||||
|
||||
TryGetFromRegistry(documents);
|
||||
TryGetFromRecentFolders(documents);
|
||||
TryGetFromJumpLists(documents);
|
||||
var useRegistry = normalizedSources.Contains(OfficeRecentDocumentSourceTypes.Registry, StringComparer.OrdinalIgnoreCase);
|
||||
var useRecentFolders = normalizedSources.Contains(OfficeRecentDocumentSourceTypes.RecentFolders, StringComparer.OrdinalIgnoreCase);
|
||||
var useJumpLists = normalizedSources.Contains(OfficeRecentDocumentSourceTypes.JumpLists, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (documents.Count < maxCount)
|
||||
if (useRegistry)
|
||||
{
|
||||
TryGetFromRegistry(documents);
|
||||
}
|
||||
|
||||
if (useRecentFolders)
|
||||
{
|
||||
TryGetFromRecentFolders(documents);
|
||||
}
|
||||
|
||||
if (useJumpLists)
|
||||
{
|
||||
TryGetFromJumpLists(documents);
|
||||
}
|
||||
|
||||
if (useRegistry && documents.Count < maxCount)
|
||||
{
|
||||
TryGetFromMudToolsInterop(documents);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
x:Class="LanMountainDesktop.Views.ComponentEditors.OfficeRecentDocumentsComponentEditor">
|
||||
<StackPanel Spacing="16">
|
||||
<Border Classes="component-editor-hero-card"
|
||||
Padding="24">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock x:Name="HeadlineTextBlock"
|
||||
Classes="component-editor-headline"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock x:Name="DescriptionTextBlock"
|
||||
Classes="component-editor-secondary-text"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="component-editor-card"
|
||||
Padding="20">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock x:Name="SourcesHeaderTextBlock"
|
||||
Classes="component-editor-section-title" />
|
||||
<TextBlock x:Name="SourcesDescriptionTextBlock"
|
||||
Classes="component-editor-secondary-text"
|
||||
TextWrapping="Wrap" />
|
||||
<CheckBox x:Name="RegistryCheckBox"
|
||||
IsCheckedChanged="OnSourceSelectionChanged" />
|
||||
<CheckBox x:Name="RecentFoldersCheckBox"
|
||||
IsCheckedChanged="OnSourceSelectionChanged" />
|
||||
<CheckBox x:Name="JumpListsCheckBox"
|
||||
IsCheckedChanged="OnSourceSelectionChanged" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<TextBlock x:Name="HintTextBlock"
|
||||
Classes="component-editor-secondary-text"
|
||||
Margin="12,0"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Avalonia.Interactivity;
|
||||
using LanMountainDesktop.ComponentSystem;
|
||||
using LanMountainDesktop.Models;
|
||||
|
||||
namespace LanMountainDesktop.Views.ComponentEditors;
|
||||
|
||||
public partial class OfficeRecentDocumentsComponentEditor : ComponentEditorViewBase
|
||||
{
|
||||
private bool _suppressEvents;
|
||||
|
||||
public OfficeRecentDocumentsComponentEditor()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public OfficeRecentDocumentsComponentEditor(DesktopComponentEditorContext? context)
|
||||
: base(context)
|
||||
{
|
||||
InitializeComponent();
|
||||
ApplyState();
|
||||
}
|
||||
|
||||
private void ApplyState()
|
||||
{
|
||||
var snapshot = LoadSnapshot();
|
||||
var enabledSources = OfficeRecentDocumentSourceTypes.NormalizeValues(
|
||||
snapshot.OfficeRecentDocumentsEnabledSources,
|
||||
useDefaultWhenEmpty: snapshot.OfficeRecentDocumentsEnabledSources is null);
|
||||
|
||||
HeadlineTextBlock.Text = Context?.Definition.DisplayName ?? "Office Recent Documents";
|
||||
DescriptionTextBlock.Text = L(
|
||||
"office_recent_documents.settings.desc",
|
||||
"Choose which Windows and Office sources this widget should scan for recent documents.");
|
||||
SourcesHeaderTextBlock.Text = L(
|
||||
"office_recent_documents.settings.sources_title",
|
||||
"Recent document sources");
|
||||
SourcesDescriptionTextBlock.Text = L(
|
||||
"office_recent_documents.settings.sources_desc",
|
||||
"You can combine multiple sources. Registry selection also keeps the Office interop MRU fallback available.");
|
||||
RegistryCheckBox.Content = L(
|
||||
"office_recent_documents.settings.source.registry",
|
||||
"Office registry MRU");
|
||||
RecentFoldersCheckBox.Content = L(
|
||||
"office_recent_documents.settings.source.recent_folders",
|
||||
"Windows Recent folders");
|
||||
JumpListsCheckBox.Content = L(
|
||||
"office_recent_documents.settings.source.jump_lists",
|
||||
"Windows Jump Lists");
|
||||
HintTextBlock.Text = L(
|
||||
"office_recent_documents.settings.hint",
|
||||
"If you disable all sources, this widget will stay empty until at least one source is enabled again.");
|
||||
|
||||
_suppressEvents = true;
|
||||
RegistryCheckBox.IsChecked = enabledSources.Contains(OfficeRecentDocumentSourceTypes.Registry, StringComparer.OrdinalIgnoreCase);
|
||||
RecentFoldersCheckBox.IsChecked = enabledSources.Contains(OfficeRecentDocumentSourceTypes.RecentFolders, StringComparer.OrdinalIgnoreCase);
|
||||
JumpListsCheckBox.IsChecked = enabledSources.Contains(OfficeRecentDocumentSourceTypes.JumpLists, StringComparer.OrdinalIgnoreCase);
|
||||
_suppressEvents = false;
|
||||
}
|
||||
|
||||
private void OnSourceSelectionChanged(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
_ = sender;
|
||||
_ = e;
|
||||
if (_suppressEvents)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedSources = new[]
|
||||
{
|
||||
RegistryCheckBox.IsChecked == true ? OfficeRecentDocumentSourceTypes.Registry : null,
|
||||
RecentFoldersCheckBox.IsChecked == true ? OfficeRecentDocumentSourceTypes.RecentFolders : null,
|
||||
JumpListsCheckBox.IsChecked == true ? OfficeRecentDocumentSourceTypes.JumpLists : null
|
||||
}
|
||||
.Where(static value => !string.IsNullOrWhiteSpace(value))
|
||||
.Cast<string>()
|
||||
.ToList();
|
||||
|
||||
var snapshot = LoadSnapshot();
|
||||
snapshot.OfficeRecentDocumentsEnabledSources = selectedSources;
|
||||
SaveSnapshot(snapshot, nameof(ComponentSettingsSnapshot.OfficeRecentDocumentsEnabledSources));
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,20 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using LanMountainDesktop.ComponentSystem;
|
||||
using LanMountainDesktop.Models;
|
||||
using LanMountainDesktop.Services;
|
||||
|
||||
namespace LanMountainDesktop.Views.Components;
|
||||
|
||||
public partial class OfficeRecentDocumentsWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget
|
||||
public partial class OfficeRecentDocumentsWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget, IComponentPlacementContextAware
|
||||
{
|
||||
private readonly IOfficeRecentDocumentsService _recentDocumentsService;
|
||||
private readonly IComponentInstanceSettingsStore _componentSettingsStore = HostComponentSettingsStoreProvider.GetOrCreate();
|
||||
private List<OfficeRecentDocument> _documents = new();
|
||||
private string _componentId = BuiltInComponentIds.DesktopOfficeRecentDocuments;
|
||||
private string _placementId = string.Empty;
|
||||
private IReadOnlyList<string> _enabledSources = OfficeRecentDocumentSourceTypes.DefaultValues;
|
||||
private bool _isOnActivePage;
|
||||
private bool _isEditMode;
|
||||
private bool _isLoading;
|
||||
@@ -20,6 +26,7 @@ public partial class OfficeRecentDocumentsWidget : UserControl, IDesktopComponen
|
||||
{
|
||||
InitializeComponent();
|
||||
_recentDocumentsService = new OfficeRecentDocumentsService();
|
||||
ReloadSettings();
|
||||
}
|
||||
|
||||
public void ApplyCellSize(double cellSize)
|
||||
@@ -44,6 +51,15 @@ public partial class OfficeRecentDocumentsWidget : UserControl, IDesktopComponen
|
||||
}
|
||||
}
|
||||
|
||||
public void SetComponentPlacementContext(string componentId, string? placementId)
|
||||
{
|
||||
_componentId = string.IsNullOrWhiteSpace(componentId)
|
||||
? BuiltInComponentIds.DesktopOfficeRecentDocuments
|
||||
: componentId.Trim();
|
||||
_placementId = placementId?.Trim() ?? string.Empty;
|
||||
ReloadSettings();
|
||||
}
|
||||
|
||||
private async void LoadDocuments()
|
||||
{
|
||||
if (_isLoading)
|
||||
@@ -54,10 +70,12 @@ public partial class OfficeRecentDocumentsWidget : UserControl, IDesktopComponen
|
||||
try
|
||||
{
|
||||
_isLoading = true;
|
||||
ReloadSettings();
|
||||
StatusTextBlock.IsVisible = false;
|
||||
DocumentsItemsControl.ItemsSource = null;
|
||||
|
||||
_documents = await Task.Run(() => _recentDocumentsService.GetRecentDocuments(20));
|
||||
var enabledSources = _enabledSources.ToArray();
|
||||
_documents = await Task.Run(() => _recentDocumentsService.GetRecentDocuments(20, enabledSources));
|
||||
|
||||
if (_documents.Count == 0)
|
||||
{
|
||||
@@ -80,6 +98,14 @@ public partial class OfficeRecentDocumentsWidget : UserControl, IDesktopComponen
|
||||
}
|
||||
}
|
||||
|
||||
private void ReloadSettings()
|
||||
{
|
||||
var snapshot = _componentSettingsStore.LoadForComponent(_componentId, _placementId);
|
||||
_enabledSources = OfficeRecentDocumentSourceTypes.NormalizeValues(
|
||||
snapshot.OfficeRecentDocumentsEnabledSources,
|
||||
useDefaultWhenEmpty: snapshot.OfficeRecentDocumentsEnabledSources is null);
|
||||
}
|
||||
|
||||
private void UpdateDisplay()
|
||||
{
|
||||
var displayItems = _documents.Select(d => new OfficeRecentDocumentViewModel
|
||||
|
||||
Reference in New Issue
Block a user