返回提交历史
Added
.editorconfig
+4
-0
Modified
LICENSE.txt
+1
-1
Added
XFENewsApplication.Core/Utilities/Helpers/FileHelper.cs
+36
-0
Added
XFENewsApplication.Core/XFENewsApplication.Core.csproj
+21
-0
Added
XFENewsApplication.Test/Program.cs
+22
-0
Added
XFENewsApplication.Test/XFENewsApplication.Test.csproj
+15
-0
Modified
XFENewsApplication.sln
+33
-0
Modified
XFENewsApplication/App.xaml
+1
-2
Modified
XFENewsApplication/App.xaml.cs
+34
-38
Modified
XFENewsApplication/MainWindow.xaml.cs
+2
-1
Added
XFENewsApplication/Profiles/CrossVersionProfiles/SystemProfile.cs
+15
-0
Added
XFENewsApplication/Styles/Thickness.xaml
+36
-0
Added
XFENewsApplication/Utilities/AppPath.cs
+8
-0
Added
XFENewsApplication/Utilities/Converter/DateTimeConverter.cs
+17
-0
Added
XFENewsApplication/ViewModels/AppShellPageViewModel.cs
+24
-0
Added
XFENewsApplication/ViewModels/SettingPageViewModel.cs
+17
-0
Added
XFENewsApplication/ViewModels/ViewModelBase.cs
+5
-0
Added
XFENewsApplication/Views/AppShellPage.xaml
+54
-0
Added
XFENewsApplication/Views/AppShellPage.xaml.cs
+115
-0
Added
XFENewsApplication/Views/NewsViewPage.xaml
+14
-0
Added
XFENewsApplication/Views/NewsViewPage.xaml.cs
+12
-0
Added
XFENewsApplication/Views/SettingPage.xaml
+104
-0
Added
XFENewsApplication/Views/SettingPage.xaml.cs
+22
-0
Modified
XFENewsApplication/XFENewsApplication.csproj
+28
-2
XFEstudio/XFENewsApplication
更新解决方案和核心功能,优化 UI 结构
- 添加对 `.editorconfig` 的支持,更新解决方案文件。 - 引入 `XFENewsApplication.Core` 和 `XFENewsApplication.Test` 项目。 - 在 `App.xaml` 中移除注释并添加 `Thickness.xaml` 资源引用。 - 重构 `App.xaml.cs`,优化命名空间引用和构造函数。 - 更新 `MainWindow.xaml.cs` 中的主题变化处理逻辑。 - 在项目文件中添加 `XFEExtension.NetCore.WinUIHelper` 引用。 - 新增 `FileHelper.cs`,实现文件路径管理和快捷方式创建。 - 在 `Program.cs` 中实现爬虫测试方法,解析新闻数据。 - 设置测试项目的基本属性和依赖项。 - 在 `SystemProfile.cs` 中实现主题管理功能。 - 新增 `Thickness.xaml`,定义 UI 布局的厚度资源。 - 创建主界面 `AppShellPage` 和新闻展示页面 `NewsViewPage`。 - 实现设置页面,允许用户配置应用选项。 - 使用 `CommunityToolkit.Mvvm` 库简化视图模型的属性管理和命令处理。
0b340e5
代码差异
24 个文件
+640
-44
@@ -0,0 +1,4 @@
1
[*.cs]
2
3
# MVVMTK0045: Using [ObservableProperty] on fields is not AOT compatible for WinRT
4
dotnet_diagnostic.MVVMTK0045.severity = none
@@ -1,6 +1,6 @@
1
1
MIT License
2
2
3
Copyright (c) [year] [fullname]
3
Copyright (c) [2025] [XFEstudio]
4
4
5
5
Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,36 @@
1
using IWshRuntimeLibrary;
2
3
namespace XFENewsApplication.Core.Utilities.Helpers;
4
5
public static class FileHelper
6
{
7
public static string[] RootPath { get; set; } = [@"C:\", @"D:\", @"E:\", @"F:\", @"G:\", @"H:\", @"I:\", @"J:\", @"K:\", @"L:\", @"M:\", @"N:\", @"O:\", @"P:\", @"Q:\", @"R:\", @"S:\", @"T:\", @"U:\", @"V:\", @"W:\", @"X:\", @"Y:\", @"Z:\",];
8
public static long GetDirectorySize(DirectoryInfo directoryInfo)
9
{
10
long size = 0;
11
FileInfo[] files = directoryInfo.GetFiles();
12
foreach (FileInfo file in files)
13
{
14
size += file.Length;
15
}
16
DirectoryInfo[] directories = directoryInfo.GetDirectories();
17
foreach (DirectoryInfo directory in directories)
18
{
19
size += GetDirectorySize(directory);
20
}
21
return size;
22
}
23
24
public static bool IsRootPath(string path) => RootPath.Any(rootPath => rootPath == path);
25
26
public static void CreateShortCut(string targetPath, string originalPath, string argument, string description = "快捷方式")
27
{
28
var wshShortcut = (IWshShortcut)new WshShell().CreateShortcut(targetPath);
29
wshShortcut.TargetPath = originalPath;
30
wshShortcut.WorkingDirectory = Path.GetDirectoryName(originalPath);
31
wshShortcut.WindowStyle = 1;
32
wshShortcut.Description = description;
33
wshShortcut.Arguments = argument;
34
wshShortcut.Save();
35
}
36
}
@@ -0,0 +1,21 @@
1
<Project Sdk="Microsoft.NET.Sdk">
2
3
<PropertyGroup>
4
<TargetFramework>net8.0</TargetFramework>
5
<ImplicitUsings>enable</ImplicitUsings>
6
<Nullable>enable</Nullable>
7
</PropertyGroup>
8
9
<ItemGroup>
10
<COMReference Include="IWshRuntimeLibrary">
11
<WrapperTool>tlbimp</WrapperTool>
12
<VersionMinor>0</VersionMinor>
13
<VersionMajor>1</VersionMajor>
14
<Guid>f935dc20-1cf0-11d0-adb9-00c04fd58a0b</Guid>
15
<Lcid>0</Lcid>
16
<Isolated>false</Isolated>
17
<EmbedInteropTypes>true</EmbedInteropTypes>
18
</COMReference>
19
</ItemGroup>
20
21
</Project>
@@ -0,0 +1,22 @@
1
using System.Text.Json;
2
using XFEExtension.NetCore.XFETransform.JsonConverter;
3
4
class Program
5
{
6
[SMTest]
7
public static async Task ClimbTest()
8
{
9
using var client = new HttpClient();
10
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0");
11
QueryableJsonNode authJsonNode = await client.GetStringAsync("https://www.msn.cn/resolver/api/resolve/v3/config/?expType=AppConfig&expInstance=default&apptype=homePage&v=20250401.183&targetScope={%22audienceMode%22:%22adult%22,%22browser%22:{%22browserType%22:%22edgeChromium%22,%22version%22:%22135%22,%22ismobile%22:%22false%22},%22deviceFormFactor%22:%22desktop%22,%22domain%22:%22www.msn.cn%22,%22locale%22:{%22content%22:{%22language%22:%22zh%22,%22market%22:%22cn%22},%22display%22:{%22language%22:%22zh%22,%22market%22:%22cn%22}},%22os%22:%22windows%22,%22platform%22:%22web%22,%22pageType%22:%22hp%22,%22pageExperiments%22:[]}");
12
var result = await client.GetStringAsync($"https://assets.msn.com/service/news/feed/pages/weblayout?User=&activityId=&adoffsets=c1:-1,c2:-1&apikey={authJsonNode["configs"]["StripeWC/default"]["properties"]["apikey"]}&audienceMode=adult&cm=zh-cn&colstatus=c1:0,c2:0&column=c2&colwidth=300&contentType=article,video,slideshow,webcontent&it=edgeid&l3v=2&layout=c2&memory=8&newsSkip=0&newsTop=48&ocid=hponeservicefeed&pgc=11&private=1&scn=APP_ANON&timeOut=1000&vpSize=721x674&wposchema=byregion");
13
using var document = JsonDocument.Parse(result);
14
int i = 0;
15
foreach (var subNode in document.RootElement.GetProperty("sections").EnumerateArray().ElementAt(0).GetProperty("cards").EnumerateArray())
16
{
17
if (i++ == 0)
18
continue;
19
Console.WriteLine($"{subNode.GetProperty("title").GetString()}\n{subNode.GetProperty("abstract").GetString()}\n{subNode.GetProperty("url").GetString()}\n");
20
}
21
}
22
}
@@ -0,0 +1,15 @@
1
<Project Sdk="Microsoft.NET.Sdk">
2
3
<PropertyGroup>
4
<OutputType>Exe</OutputType>
5
<TargetFramework>net8.0</TargetFramework>
6
<ImplicitUsings>enable</ImplicitUsings>
7
<Nullable>enable</Nullable>
8
</PropertyGroup>
9
10
<ItemGroup>
11
<PackageReference Include="XFEExtension.NetCore" Version="3.3.1" />
12
<PackageReference Include="XFEExtension.NetCore.XUnit" Version="2.0.4" />
13
</ItemGroup>
14
15
</Project>
@@ -4,6 +4,15 @@ VisualStudioVersion = 17.14.35821.62
4
4
MinimumVisualStudioVersion = 10.0.40219.1
5
5
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XFENewsApplication", "XFENewsApplication\XFENewsApplication.csproj", "{A8E05536-352A-43C6-853E-836AC45DDC16}"
6
6
EndProject
7
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
8
ProjectSection(SolutionItems) = preProject
9
.editorconfig = .editorconfig
10
EndProjectSection
11
EndProject
12
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XFENewsApplication.Core", "XFENewsApplication.Core\XFENewsApplication.Core.csproj", "{40D6FFA5-FAD0-4E3A-9385-610C21610289}"
13
EndProject
14
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XFENewsApplication.Test", "XFENewsApplication.Test\XFENewsApplication.Test.csproj", "{85F9634D-738C-4E73-BBAA-77A97F014F26}"
15
EndProject
7
16
Global
8
17
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9
18
Debug|ARM64 = Debug|ARM64
@@ -32,6 +41,30 @@ Global
32
41
{A8E05536-352A-43C6-853E-836AC45DDC16}.Release|x86.ActiveCfg = Release|x86
33
42
{A8E05536-352A-43C6-853E-836AC45DDC16}.Release|x86.Build.0 = Release|x86
34
43
{A8E05536-352A-43C6-853E-836AC45DDC16}.Release|x86.Deploy.0 = Release|x86
44
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Debug|ARM64.ActiveCfg = Debug|Any CPU
45
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Debug|ARM64.Build.0 = Debug|Any CPU
46
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Debug|x64.ActiveCfg = Debug|Any CPU
47
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Debug|x64.Build.0 = Debug|Any CPU
48
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Debug|x86.ActiveCfg = Debug|Any CPU
49
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Debug|x86.Build.0 = Debug|Any CPU
50
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Release|ARM64.ActiveCfg = Release|Any CPU
51
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Release|ARM64.Build.0 = Release|Any CPU
52
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Release|x64.ActiveCfg = Release|Any CPU
53
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Release|x64.Build.0 = Release|Any CPU
54
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Release|x86.ActiveCfg = Release|Any CPU
55
{40D6FFA5-FAD0-4E3A-9385-610C21610289}.Release|x86.Build.0 = Release|Any CPU
56
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Debug|ARM64.ActiveCfg = Debug|Any CPU
57
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Debug|ARM64.Build.0 = Debug|Any CPU
58
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Debug|x64.ActiveCfg = Debug|Any CPU
59
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Debug|x64.Build.0 = Debug|Any CPU
60
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Debug|x86.ActiveCfg = Debug|Any CPU
61
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Debug|x86.Build.0 = Debug|Any CPU
62
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Release|ARM64.ActiveCfg = Release|Any CPU
63
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Release|ARM64.Build.0 = Release|Any CPU
64
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Release|x64.ActiveCfg = Release|Any CPU
65
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Release|x64.Build.0 = Release|Any CPU
66
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Release|x86.ActiveCfg = Release|Any CPU
67
{85F9634D-738C-4E73-BBAA-77A97F014F26}.Release|x86.Build.0 = Release|Any CPU
35
68
EndGlobalSection
36
69
GlobalSection(SolutionProperties) = preSolution
37
70
HideSolutionNode = FALSE
@@ -8,9 +8,8 @@
8
8
<ResourceDictionary>
9
9
<ResourceDictionary.MergedDictionaries>
10
10
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
11
<!-- Other merged dictionaries here -->
11
<ResourceDictionary Source="/Styles/Thickness.xaml" />
12
12
</ResourceDictionary.MergedDictionaries>
13
<!-- Other app resources here -->
14
13
</ResourceDictionary>
15
14
</Application.Resources>
16
15
</Application>
@@ -1,50 +1,46 @@
1
using System;
2
using System.Collections.Generic;
3
using System.IO;
4
using System.Linq;
5
using System.Runtime.InteropServices.WindowsRuntime;
6
using Microsoft.UI.Xaml;
7
using Microsoft.UI.Xaml.Controls;
8
using Microsoft.UI.Xaml.Controls.Primitives;
9
using Microsoft.UI.Xaml.Data;
10
using Microsoft.UI.Xaml.Input;
11
using Microsoft.UI.Xaml.Media;
12
using Microsoft.UI.Xaml.Navigation;
13
using Microsoft.UI.Xaml.Shapes;
14
using Windows.ApplicationModel;
15
using Windows.ApplicationModel.Activation;
16
using Windows.Foundation;
17
using Windows.Foundation.Collections;
1
using XFEExtension.NetCore.WinUIHelper.Interface.Services;
2
using XFEExtension.NetCore.WinUIHelper.Utilities;
3
using XFEExtension.NetCore.WinUIHelper.Utilities.Helper;
4
using XFENewsApplication.Profiles.CrossVersionProfiles;
18
5
19
// To learn more about WinUI, the WinUI project structure,
20
// and more about our project templates, see: http://aka.ms/winui-project-info.
6
namespace XFENewsApplication;
21
7
22
namespace XFENewsApplication
8
/// <summary>
9
/// Provides application-specific behavior to supplement the default Application class.
10
/// </summary>
11
public partial class App : Application
23
12
{
13
public static MainWindow MainWindow { get; set; } = new();
24
14
/// <summary>
25
/// Provides application-specific behavior to supplement the default Application class.
15
/// Initializes the singleton application object. This is the first line of authored code
16
/// executed, and as such is the logical equivalent of main() or WinMain().
26
17
/// </summary>
27
public partial class App : Application
18
public App()
28
19
{
29
/// <summary>
30
/// Initializes the singleton application object. This is the first line of authored code
31
/// executed, and as such is the logical equivalent of main() or WinMain().
32
/// </summary>
33
public App()
34
{
35
this.InitializeComponent();
36
}
20
this.InitializeComponent();
21
AppThemeHelper.MainWindow = MainWindow;
22
AppThemeHelper.Theme = SystemProfile.Theme;
23
PageManager.RegisterPage(typeof(AppShellPage));
24
PageManager.RegisterPage(typeof(NewsViewPage));
25
UnhandledException += App_UnhandledException;
26
}
37
27
38
/// <summary>
39
/// Invoked when the application is launched.
40
/// </summary>
41
/// <param name="args">Details about the launch request and process.</param>
42
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
28
private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
29
{
30
if (ServiceManager.GetService<IMessageService>() is IMessageService messageService)
43
31
{
44
m_window = new MainWindow();
45
m_window.Activate();
32
messageService.ShowMessage(e.Message, "发生错误", InfoBarSeverity.Error);
33
e.Handled = true;
46
34
}
35
}
47
36
48
private Window? m_window;
37
/// <summary>
38
/// Invoked when the application is launched.
39
/// </summary>
40
/// <param name="args">Details about the launch request and process.</param>
41
protected override void OnLaunched(LaunchActivatedEventArgs args)
42
{
43
MainWindow.Content = new AppShellPage();
44
MainWindow.Activate();
49
45
}
50
46
}
@@ -1,5 +1,6 @@
1
1
using Microsoft.UI.Xaml;
2
2
using Windows.UI.ViewManagement;
3
using XFEExtension.NetCore.WinUIHelper.Utilities.Helper;
3
4
4
5
namespace XFENewsApplication;
5
6
@@ -15,6 +16,6 @@ public sealed partial class MainWindow : Window
15
16
ExtendsContentIntoTitleBar = true;
16
17
AppWindow.SetIcon(Path.Combine(AppContext.BaseDirectory, "Assets/Icons/EditorIcon.ico"));
17
18
AppWindow.TitleBar.PreferredHeightOption = Microsoft.UI.Windowing.TitleBarHeightOption.Tall;
18
UISettings.ColorValuesChanged += (_, _) => DispatcherQueue.TryEnqueue(() => AppThemeHelper.ChangeTheme(SystemProfile.Theme));
19
UISettings.ColorValuesChanged += (_, _) => DispatcherQueue.TryEnqueue(() => AppThemeHelper.ChangeTheme(AppThemeHelper.Theme));
19
20
}
20
21
}
@@ -0,0 +1,15 @@
1
using XFEExtension.NetCore.AutoConfig;
2
using XFEExtension.NetCore.WinUIHelper.Utilities;
3
using XFEExtension.NetCore.WinUIHelper.Utilities.Helper;
4
5
namespace XFENewsApplication.Profiles.CrossVersionProfiles;
6
7
public partial class SystemProfile : XFEProfile
8
{
9
public SystemProfile() => ProfilePath = $@"{AppPathHelper.LocalProfile}\{nameof(SystemProfile)}";
10
11
[ProfileProperty]
12
private ElementTheme theme;
13
14
static partial void SetThemeProperty(ref ElementTheme value) => AppThemeHelper.ChangeTheme(value);
15
}
@@ -0,0 +1,36 @@
1
<ResourceDictionary
2
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
4
5
<Thickness x:Key="LargeTopMargin">0,36,0,0</Thickness>
6
<Thickness x:Key="LargeTopBottomMargin">0,36,0,36</Thickness>
7
8
<Thickness x:Key="MediumTopMargin">0,24,0,0</Thickness>
9
<Thickness x:Key="MediumTopBottomMargin">0,24,0,24</Thickness>
10
<Thickness x:Key="MediumLeftRightMargin">24,0,24,0</Thickness>
11
<Thickness x:Key="MediumBottomMargin">0,0,0,24</Thickness>
12
13
<Thickness x:Key="SmallLeftMargin">12,0,0,0</Thickness>
14
<Thickness x:Key="SmallLeftRightMargin">12,0,12,0</Thickness>
15
<Thickness x:Key="SmallTopMargin">0,12,0,0</Thickness>
16
<Thickness x:Key="SmallRightMargin">0,0,12,0</Thickness>
17
<Thickness x:Key="SmallTopBottomMargin">0,12,0,12</Thickness>
18
19
<Thickness x:Key="XSmallLeftMargin">8,0,0,0</Thickness>
20
<Thickness x:Key="XSmallTopMargin">0,8,0,0</Thickness>
21
<Thickness x:Key="XSmallLeftTopRightBottomMargin">8,8,8,8</Thickness>
22
23
<Thickness x:Key="XXSmallTopMargin">0,4,0,0</Thickness>
24
<Thickness x:Key="XXSmallLeftTopRightBottomMargin">4,4,4,4</Thickness>
25
26
<Thickness x:Key="NavigationViewContentGridBorderThickness">1,1,0,0</Thickness>
27
<CornerRadius x:Key="NavigationViewContentGridCornerRadius">8,0,0,0</CornerRadius>
28
<Thickness x:Key="NavigationViewContentMargin">0,48,0,0</Thickness>
29
<Thickness x:Key="NavigationViewHeaderMargin">56,34,0,0</Thickness>
30
<Thickness x:Key="NavigationViewPageContentMargin">56,24,56,0</Thickness>
31
32
<Thickness x:Key="MenuBarContentMargin">36,24,36,0</Thickness>
33
34
<Thickness x:Key="SettingsPageHyperlinkButtonMargin">-12,4,0,0</Thickness>
35
36
</ResourceDictionary>