XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

ChaoXingAutoClass

【WinUI】基于 XFEstudio 的 XFEWinUIApplication 模板重建的 WinUI 3 课程工作台。二维码和账号密码登录、课程 GridView、章节、播放进度、学习笔记及日志均使用原生 WinUI 控件。网页播放器运行在独立后台进程中,界面不显示课程网站。

公开
关注 0 Fork 0 Star 0
UTF-8
using XFEExtension.NetCore.WinUIHelper.Interface.Services;
using XFEExtension.NetCore.WinUIHelper.Utilities;
using XFEExtension.NetCore.WinUIHelper.Utilities.Helper;
using XFEExtension.NetCore.XFEConsole;
using ChaoXingAutoClass.Profiles.CrossVersionProfiles;
using ChaoXingAutoClass.Profiles.CacheProfiles;
using ChaoXingAutoClass.Utilities;
using ChaoXingAutoClass.Implements.Services;
using ChaoXingAutoClass.Interface.Services;

namespace ChaoXingAutoClass
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    public partial class App : Application
    {
        /// <summary>
        /// 主页窗口
        /// </summary>
        public static MainWindow MainWindow { get; private set; } = null!;
        public static ILearningService Learning { get; } = new LearningService();
        private bool _closing;

        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            XFEConsole.UseXFEConsoleLog();
            XFEConsole.Log.LogPath = $@"{AppPath.LogDictionary}\{DateTime.Now:yyyy-M-d_HH-mm-ss}.log";
            Console.WriteLine("正在启动应用程序...");
            this.InitializeComponent();
            AppThemeHelper.Theme = SystemProfile.Theme;
            ServiceManager.RegisterGlobalService(Learning);
            PageManager.RegisterPage(typeof(AppShellPage));
            PageManager.RegisterPage(typeof(MainPage));
            PageManager.RegisterPage(typeof(LogViewPage));
            PageManager.RegisterPage(typeof(SettingPage));
            PageManager.RegisterPage(typeof(CoursePage));
            UnhandledException += App_UnhandledException;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        }

        private static void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is not Exception ex) return;
            Console.WriteLine($"[ERROR]应用程序发生错误:{ex.Message}");
            Console.WriteLine($"[TRACE]{ex.StackTrace}");
            if (ServiceManager.GetService<IMessageService>() is not { } messageService) return;
            messageService.ShowMessage(ex.Message, "发生错误", InfoBarSeverity.Error);
        }

        private static void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
        {
            Console.WriteLine($"[ERROR]应用程序发生错误:{e.Message}");
            Console.WriteLine($"[TRACE]{e.Exception.StackTrace}");
            if (ServiceManager.GetService<IMessageService>() is not { } messageService) return;
            messageService.ShowMessage(e.Message, "发生错误", InfoBarSeverity.Error);
            e.Handled = true;
        }

        /// <summary>
        /// Invoked when the application is launched.
        /// </summary>
        /// <param name="args">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs args)
        {
            MainWindow = new();
            MainWindow.AppWindow.Closing += async (_, e) =>
            {
                if (_closing) return;
                e.Cancel = true;
                _closing = true;
                await Learning.DisposeAsync();
                SystemProfile.SaveProfile();
                CacheProfile.SaveProfile();
                MainWindow.Close();
            };
            MainWindow.Content = new AppShellPage();
            MainWindow.Activate();
            AppThemeHelper.MainWindow = MainWindow;
            Console.WriteLine("应用程序已启动");
            var arguments = Environment.GetCommandLineArgs();
            var liveIndex = Array.IndexOf(arguments, "--live-course");
            var parallelIndex = Array.IndexOf(arguments, "--live-parallel");
            var homeworkIndex = Array.IndexOf(arguments, "--live-homework-course");
            if (homeworkIndex >= 0 && arguments.ElementAtOrDefault(homeworkIndex + 1) is { } homeworkCourse)
                MainWindow.DispatcherQueue.TryEnqueue(async () =>
                {
                    try
                    {
                        var course = (await Learning.RefreshCoursesAsync(CancellationToken.None)).Single(c => c.Title == homeworkCourse);
                        AppShellPage.Current!.ViewModel.NavigationViewService.NavigateTo<CoursePage>(course);
                        await CoursePage.Current!.Initialization;
                        var nameIndex = Array.IndexOf(arguments, "--homework-title");
                        var name = nameIndex >= 0 ? arguments.ElementAtOrDefault(nameIndex + 1) : null;
                        var selected = name is null ? null : Learning.GetJob(course)!.Homeworks.Where(h => h.Title == name).Select(h => h.Id).ToHashSet();
                        if (selected is { Count: 0 }) throw new InvalidOperationException("未找到指定作业。");
                        await Learning.StartCourseAsync(course, 0, null, true, CancellationToken.None, homeworkIds: selected);
                    }
                    catch (Exception error) { Console.WriteLine("[ERROR]" + error); }
                });
            if (parallelIndex >= 0 && arguments.ElementAtOrDefault(parallelIndex + 1) is { } courseNames)
                MainWindow.DispatcherQueue.TryEnqueue(async () =>
                {
                    try
                    {
                        var courses = await Learning.RefreshCoursesAsync(CancellationToken.None);
                        var prefixesIndex = Array.IndexOf(arguments, "--chapter-prefixes");
                        var prefixes = (prefixesIndex >= 0 ? arguments.ElementAtOrDefault(prefixesIndex + 1) : null)?.Split('|');
                        var limitIndex = Array.IndexOf(arguments, "--chapter-limit");
                        var limit = limitIndex >= 0 && int.TryParse(arguments.ElementAtOrDefault(limitIndex + 1), out var n) ? n : 1;
                        var runs = new List<Task>(); var titles = courseNames.Split('|');
                        for (var i = 0; i < titles.Length; i++)
                        {
                            var course = courses.Single(c => c.Title == titles[i]);
                            await Learning.OpenCourseAsync(course, CancellationToken.None);
                            var chapters = Learning.GetJob(course)!.Chapters;
                            var prefix = prefixes?.ElementAtOrDefault(i);
                            var start = string.IsNullOrEmpty(prefix) ? 0 : chapters.ToList().FindIndex(c => c.Title.StartsWith(prefix + " ", StringComparison.Ordinal) || c.Title == prefix);
                            if (start < 0) throw new InvalidOperationException("未找到指定起始章节。");
                            runs.Add(Learning.StartCourseAsync(course, start, limit, false, CancellationToken.None, includeHomework: false));
                        }
                        await Task.WhenAll(runs);
                    }
                    catch (Exception error) { Console.WriteLine("[ERROR]" + error); }
                });
            if (liveIndex >= 0 && arguments.ElementAtOrDefault(liveIndex + 1) is { } title)
                MainWindow.DispatcherQueue.TryEnqueue(async () =>
                {
                    try
                    {
                        var courses = await Learning.RefreshCoursesAsync(CancellationToken.None);
                        var course = courses.Single(c => c.Title == title);
                        AppShellPage.Current!.ViewModel.NavigationViewService.NavigateTo<CoursePage>(course);
                        await CoursePage.Current!.Initialization;
                        var startIndex = Array.IndexOf(arguments, "--start-chapter");
                        if (startIndex >= 0 && arguments.ElementAtOrDefault(startIndex + 1) is { } prefix)
                        {
                            var chapterIndex = CoursePage.Current.ViewModel.Chapters.ToList().FindIndex(chapter => chapter.Title.StartsWith(prefix + " ", StringComparison.Ordinal) || chapter.Title == prefix);
                            if (chapterIndex < 0) throw new InvalidOperationException("未找到指定起始章节。");
                            CoursePage.Current.ViewModel.SelectedIndex = chapterIndex;
                        }
                        CoursePage.Current.ViewModel.ChapterLimit = int.TryParse(arguments.ElementAtOrDefault(liveIndex + 2), out var count) ? count : 3;
                        CoursePage.Current.ViewModel.ContinueAll = false;
                        await CoursePage.Current.ViewModel.StartCommand.ExecuteAsync(null);
                    }
                    catch (Exception error) { Console.WriteLine("[ERROR]" + error); }
                });
        }
    }
}