diff --git a/.github/ISSUE_TEMPLATE/bug-en.yml b/.github/ISSUE_TEMPLATE/bug-en.yml index c17116f..82fccc0 100644 --- a/.github/ISSUE_TEMPLATE/bug-en.yml +++ b/.github/ISSUE_TEMPLATE/bug-en.yml @@ -10,8 +10,6 @@ body: options: - label: I have looked up relevant Issue required: false - - label: I've read [How To Ask Questions](https://github.com/betaseeker/How-To-Ask-Questions) - required: false - type: textarea id: description attributes: @@ -24,7 +22,7 @@ body: attributes: label: Application version description: Enter the version you are using - placeholder: E.g. 0.0.0.1 + placeholder: E.g. 0.0.1 validations: required: true - type: input diff --git a/.github/ISSUE_TEMPLATE/bug-zh.yml b/.github/ISSUE_TEMPLATE/bug-zh.yml index b9b154a..677a03d 100644 --- a/.github/ISSUE_TEMPLATE/bug-zh.yml +++ b/.github/ISSUE_TEMPLATE/bug-zh.yml @@ -10,8 +10,6 @@ body: options: - label: 我查找过相关的 Issue required: false - - label: 我阅读过[提问的艺术](https://github.com/betaseeker/How-To-Ask-Questions) - required: false - type: textarea id: description attributes: @@ -24,7 +22,7 @@ body: attributes: label: 应用版本 description: 请填写你正在使用的版本 - placeholder: 如 0.0.0.1 + placeholder: 如 0.0.1 validations: required: true - type: input diff --git a/.github/ISSUE_TEMPLATE/feat-en.yml b/.github/ISSUE_TEMPLATE/feat-en.yml index 84c5c27..7aa68bf 100644 --- a/.github/ISSUE_TEMPLATE/feat-en.yml +++ b/.github/ISSUE_TEMPLATE/feat-en.yml @@ -10,8 +10,6 @@ body: options: - label: I have looked up relevant Issue required: false - - label: I've read [How To Ask Questions](https://github.com/betaseeker/How-To-Ask-Questions) - required: false - type: textarea id: description attributes: @@ -24,7 +22,7 @@ body: attributes: label: Application version description: Enter the version you are using - placeholder: E.g. 0.0.0.1 + placeholder: E.g. 0.0.1 validations: required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/feat-zh.yml b/.github/ISSUE_TEMPLATE/feat-zh.yml index 6fa70fd..82d00d9 100644 --- a/.github/ISSUE_TEMPLATE/feat-zh.yml +++ b/.github/ISSUE_TEMPLATE/feat-zh.yml @@ -10,8 +10,6 @@ body: options: - label: 我查找过相关的 Issue required: false - - label: 我阅读过[提问的艺术](https://github.com/betaseeker/How-To-Ask-Questions) - required: false - type: textarea id: description attributes: @@ -24,7 +22,7 @@ body: attributes: label: 应用版本 description: 请填写你正在使用的版本 - placeholder: 如 0.0.0.1 + placeholder: 如 0.0.1 validations: required: true - type: textarea diff --git a/.github/workflows/auto-assign.yml b/.github/workflows/auto-assign.yml deleted file mode 100644 index 9c61cc3..0000000 --- a/.github/workflows/auto-assign.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Auto Assign -on: - issues: - types: [opened] - pull_request: - types: [opened] -jobs: - run: - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - name: 'Auto-assign issue' - uses: pozil/auto-assign-issue@v1 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - assignees: AuroraZiling - numOfAssignee: 1 \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index f65b9ef..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: "PipManager Continuous Integration" - -on: - push: - branches: - - development - -jobs: - build: - runs-on: windows-latest - env: - Project_Path: src/PipManager/PipManager.csproj - Executable_Path: publish/PipManager.exe - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Install .Net 8 - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.x - - - name: Restore - run: dotnet restore ${{ env.Project_Path }} - - - name: Build - run: dotnet build ${{ env.Project_Path }} -c Release --no-restore - - - name: Publish - run: dotnet publish ${{ env.Project_Path }} -c Release -r win-x64 -o "publish/" -p:Platform=x64 -p:PublishReadyToRun=false -p:EnableCompressionInSingleFile=false -p:PublishSingleFile=true -p:SelfContained=false -p:AssemblyVersion=1.0.0.0 - - - name: Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: PipManager-dev - path: ${{ env.Executable_Path }} \ No newline at end of file diff --git a/README.md b/README.md index 5e46c93..77ce194 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@
- - Logo + + Logo

Pip Manager

@@ -14,11 +14,11 @@ Explore the docs (Chinese Simplified) »

- Screenshots + Screenshots · - Report Bug + Report Bug · - Request Feature + Request Feature

@@ -33,9 +33,7 @@ --- -该项目处于早期开发阶段,存在大量Bug - -The project is in an early stage of development and has a lot of bugs +该项目现已依赖[PipManager.Core](https://github.com/Pip-Manager/PipManager.Core)并逐渐迁移 --- @@ -50,7 +48,9 @@ Features: Easier operation of Pip is the goal of Pip Manager. -### Technology Stack +### Technology + +language csharp Pip Manager is based on the following technology stacks: @@ -74,7 +74,7 @@ Double click `PipManager.exe` or `PipManager_withRuntime.exe` *If you have not i

(back to top)

-See the [Open Issues](https://github.com/AuroraZiling/PipManager/issues) for a full list of proposed features (and known issues). +See the [Open Issues](https://github.com/Pip-Manager/PipManager.Wpf/issues) for a full list of proposed features (and known issues). ## Contributing @@ -89,16 +89,18 @@ See the [Open Issues](https://github.com/AuroraZiling/PipManager/issues) for a f Distributed under the MIT License. See `LICENSE` for more information. +Kawaii `C#` Logo in [Technology Stack](#technology-stack) is created by [SAWATSUKI](https://github.com/SAWARATSUKI) +

(back to top)

-[github-downloads-shield]: https://img.shields.io/github/downloads/AuroraZiling/PipManager/total.svg?style=for-the-badge&color=blue -[github-downloads-url]: https://github.com/AuroraZiling/PipManager/releases -[stars-shield]: https://img.shields.io/github/stars/AuroraZiling/PipManager.svg?style=for-the-badge -[stars-url]: https://github.com/AuroraZiling/PipManager/stargazers -[issues-shield]: https://img.shields.io/github/issues/AuroraZiling/PipManager.svg?style=for-the-badge -[issues-url]: https://github.com/AuroraZiling/PipManager/issues -[license-shield]: https://img.shields.io/github/license/AuroraZiling/PipManager.svg?style=for-the-badge -[license-url]: https://github.com/AuroraZiling/PipManager/blob/master/LICENSE.txt +[github-downloads-shield]: https://img.shields.io/github/downloads/Pip-Manager/PipManager.Wpf/total.svg?style=for-the-badge&color=blue +[github-downloads-url]: https://github.com/Pip-Manager/PipManager.Wpf/releases +[stars-shield]: https://img.shields.io/github/stars/Pip-Manager/PipManager.Wpf.svg?style=for-the-badge +[stars-url]: https://github.com/Pip-Manager/PipManager.Wpf/stargazers +[issues-shield]: https://img.shields.io/github/issues/Pip-Manager/PipManager.Wpf.svg?style=for-the-badge +[issues-url]: https://github.com/Pip-Manager/PipManager.Wpf/issues +[license-shield]: https://img.shields.io/github/license/Pip-Manager/PipManager.Wpf.svg?style=for-the-badge +[license-url]: https://github.com/Pip-Manager/PipManager.Wpf/blob/master/LICENSE.txt [screenshot]: images/screenshot.png [.NET Core]: https://img.shields.io/badge/.NET_Core-512BD4?style=for-the-badge&logo=dotnet&logoColor=white [.NET-url]: https://dotnet.microsoft.com/ diff --git a/build.ps1 b/build.ps1 index 19247d5..5e313d5 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,19 +1,19 @@ param( [string] $Architecture = "x64", - [string] $Version = "0.0.4.0" + [string] $Version = "0.1.0.0" ) $ErrorActionPreference = "Stop"; Write-Output "Start building singleWithRuntime..."; -dotnet publish src/PipManager/PipManager.csproj -c Release -r "win-$Architecture" -o "build/$Version/singleWithRuntime" -p:Platform=$Architecture -p:PublishReadyToRun=true -p:EnableCompressionInSingleFile=true -p:PublishSingleFile=true -p:SelfContained=true -p:AssemblyVersion=$Version -p:Configuration=Release; +dotnet publish src/PipManager.Windows.csproj -c Release -r "win-$Architecture" -o "build/$Version/singleWithRuntime" -p:Platform=$Architecture -p:PublishReadyToRun=true -p:EnableCompressionInSingleFile=true -p:PublishSingleFile=true -p:SelfContained=true -p:AssemblyVersion=$Version -p:Configuration=Release; Rename-Item -Path "build/$Version/singleWithRuntime/PipManager.exe" -NewName "PipManager_withRuntime.exe" Write-Output "Start building singleWithoutRuntime..."; -dotnet publish src/PipManager/PipManager.csproj -c Release -r "win-$Architecture" -o "build/$Version/singleWithoutRuntime" -p:Platform=$Architecture -p:PublishReadyToRun=false -p:EnableCompressionInSingleFile=false -p:PublishSingleFile=true -p:SelfContained=false -p:AssemblyVersion=$Version -p:Configuration=Release; +dotnet publish src/PipManager.Windows.csproj -c Release -r "win-$Architecture" -o "build/$Version/singleWithoutRuntime" -p:Platform=$Architecture -p:PublishReadyToRun=false -p:EnableCompressionInSingleFile=false -p:PublishSingleFile=true -p:SelfContained=false -p:AssemblyVersion=$Version -p:Configuration=Release; Write-Output "Build Finished"; diff --git a/src/PipManager/.editorconfig b/src/.editorconfig similarity index 100% rename from src/PipManager/.editorconfig rename to src/.editorconfig diff --git a/src/.gitattributes b/src/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/src/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/src/PipManager/App.xaml b/src/App.xaml similarity index 73% rename from src/PipManager/App.xaml rename to src/App.xaml index 7454926..4f0ce02 100644 --- a/src/PipManager/App.xaml +++ b/src/App.xaml @@ -1,45 +1,45 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - + - - + + - + + IsIndeterminate="True" + Width="100" /> + Margin="0,15,0,0" /> + Margin="0,7,0,0" /> - + @@ -50,7 +50,7 @@ - + @@ -58,13 +58,12 @@ - - + + - \ No newline at end of file diff --git a/src/PipManager/App.xaml.cs b/src/App.xaml.cs similarity index 79% rename from src/PipManager/App.xaml.cs rename to src/App.xaml.cs index f3a2384..f25a77f 100644 --- a/src/PipManager/App.xaml.cs +++ b/src/App.xaml.cs @@ -2,45 +2,47 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using PipManager.PackageSearch; -using PipManager.Services; -using PipManager.Services.Action; -using PipManager.Services.Configuration; -using PipManager.Services.Environment; -using PipManager.Services.Mask; -using PipManager.Services.Toast; -using PipManager.ViewModels.Pages.Action; -using PipManager.ViewModels.Pages.Environment; -using PipManager.ViewModels.Pages.Lab; -using PipManager.ViewModels.Pages.Library; -using PipManager.ViewModels.Pages.Search; -using PipManager.ViewModels.Pages.Tools; -using PipManager.ViewModels.Windows; -using PipManager.Views.Pages.About; -using PipManager.Views.Pages.Action; -using PipManager.Views.Pages.Environment; -using PipManager.Views.Pages.Lab; -using PipManager.Views.Pages.Library; -using PipManager.Views.Pages.Search; -using PipManager.Views.Pages.Settings; -using PipManager.Views.Pages.Tools; -using PipManager.Views.Windows; using Serilog; using System.IO; using System.Net; using System.Net.Http; using System.Runtime.InteropServices; using System.Windows.Threading; -using PipManager.ViewModels.Pages.Overlay; -using PipManager.Views.Pages.Overlay; +using PipManager.Core.Services.PackageSearchService; +using PipManager.Windows.Services; +using PipManager.Windows.Services.Action; +using PipManager.Windows.Services.Configuration; +using PipManager.Windows.Services.Environment; +using PipManager.Windows.Services.Mask; +using PipManager.Windows.Services.Overlay; +using PipManager.Windows.Services.Toast; +using PipManager.Windows.ViewModels.Pages.Action; +using PipManager.Windows.ViewModels.Pages.Environment; +using PipManager.Windows.ViewModels.Pages.Lab; +using PipManager.Windows.ViewModels.Pages.Library; +using PipManager.Windows.ViewModels.Pages.Overlay; +using PipManager.Windows.ViewModels.Pages.Search; +using PipManager.Windows.ViewModels.Pages.Tools; +using PipManager.Windows.ViewModels.Windows; +using PipManager.Windows.Views.Pages.About; +using PipManager.Windows.Views.Pages.Action; +using PipManager.Windows.Views.Pages.Environment; +using PipManager.Windows.Views.Pages.Lab; +using PipManager.Windows.Views.Pages.Library; +using PipManager.Windows.Views.Pages.Overlay; +using PipManager.Windows.Views.Pages.Search; +using PipManager.Windows.Views.Pages.Settings; +using PipManager.Windows.Views.Pages.Tools; +using PipManager.Windows.Views.Windows; using Wpf.Ui; -using AboutViewModel = PipManager.ViewModels.Pages.About.AboutViewModel; -using ActionViewModel = PipManager.ViewModels.Pages.Action.ActionViewModel; -using LibraryViewModel = PipManager.ViewModels.Pages.Library.LibraryViewModel; -using SearchViewModel = PipManager.ViewModels.Pages.Search.SearchViewModel; -using SettingsViewModel = PipManager.ViewModels.Pages.Settings.SettingsViewModel; -namespace PipManager; +namespace PipManager.Windows; + +using AboutViewModel = ViewModels.Pages.About.AboutViewModel; +using ActionViewModel = ViewModels.Pages.Action.ActionViewModel; +using LibraryViewModel = ViewModels.Pages.Library.LibraryViewModel; +using SearchViewModel = ViewModels.Pages.Search.SearchViewModel; +using SettingsViewModel = ViewModels.Pages.Settings.SettingsViewModel; /// /// Interaction logic for App.xaml @@ -62,7 +64,7 @@ public partial class App services.AddTransient(_ => { var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All }) { DefaultRequestVersion = HttpVersion.Version20 }; - client.DefaultRequestHeaders.Add("User-Agent", $"PipManager/{AppInfo.AppVersion}"); + client.DefaultRequestHeaders.Add("User-Agent", $"PipManager.Windows/{AppInfo.AppVersion}"); client.Timeout = TimeSpan.FromSeconds(6); return client; }); @@ -83,6 +85,7 @@ public partial class App services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); // Pages services.AddSingleton(); @@ -107,6 +110,7 @@ public partial class App services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); diff --git a/src/PipManager/AppInfo.cs b/src/AppInfo.cs similarity index 95% rename from src/PipManager/AppInfo.cs rename to src/AppInfo.cs index 3e9da3c..e0cfabe 100644 --- a/src/PipManager/AppInfo.cs +++ b/src/AppInfo.cs @@ -1,7 +1,7 @@ using System.IO; using System.Reflection; -namespace PipManager; +namespace PipManager.Windows; public static class AppInfo { diff --git a/src/PipManager/AppStarting.cs b/src/AppStarting.cs similarity index 97% rename from src/PipManager/AppStarting.cs rename to src/AppStarting.cs index dfb18ce..9564176 100644 --- a/src/PipManager/AppStarting.cs +++ b/src/AppStarting.cs @@ -1,12 +1,12 @@ -using PipManager.Models; -using PipManager.Services.Configuration; +using PipManager.Windows.Services.Configuration; using Serilog; using System.Globalization; using System.IO; using System.Runtime.InteropServices; -using PipManager.Helpers; +using PipManager.Windows.Helpers; +using PipManager.Windows.Models; -namespace PipManager; +namespace PipManager.Windows; public partial class AppStarting { diff --git a/src/PipManager/AssemblyInfo.cs b/src/AssemblyInfo.cs similarity index 100% rename from src/PipManager/AssemblyInfo.cs rename to src/AssemblyInfo.cs diff --git a/src/PipManager/Assets/icon.ico b/src/Assets/icon.ico similarity index 100% rename from src/PipManager/Assets/icon.ico rename to src/Assets/icon.ico diff --git a/src/PipManager/Assets/icon.png b/src/Assets/icon.png similarity index 100% rename from src/PipManager/Assets/icon.png rename to src/Assets/icon.png diff --git a/src/PipManager/Assets/logo/python-logo-only.png b/src/Assets/logo/python-logo-only.png similarity index 100% rename from src/PipManager/Assets/logo/python-logo-only.png rename to src/Assets/logo/python-logo-only.png diff --git a/src/PipManager/Controls/ContentDialogCreateOptions.cs b/src/Controls/ContentDialogCreateOptions.cs similarity index 92% rename from src/PipManager/Controls/ContentDialogCreateOptions.cs rename to src/Controls/ContentDialogCreateOptions.cs index f6cb41c..d43d121 100644 --- a/src/PipManager/Controls/ContentDialogCreateOptions.cs +++ b/src/Controls/ContentDialogCreateOptions.cs @@ -1,7 +1,7 @@ -using PipManager.Languages; +using PipManager.Windows.Languages; using Wpf.Ui; -namespace PipManager.Controls; +namespace PipManager.Windows.Controls; public static class ContentDialogCreateOptions { diff --git a/src/PipManager/Controls/Mask/MaskPresenter.cs b/src/Controls/Mask/MaskPresenter.cs similarity index 93% rename from src/PipManager/Controls/Mask/MaskPresenter.cs rename to src/Controls/Mask/MaskPresenter.cs index 22650e5..ac6fc43 100644 --- a/src/PipManager/Controls/Mask/MaskPresenter.cs +++ b/src/Controls/Mask/MaskPresenter.cs @@ -1,6 +1,6 @@ using System.Windows.Controls; -namespace PipManager.Controls.Mask; +namespace PipManager.Windows.Controls.Mask; public class MaskPresenter : ContentPresenter { diff --git a/src/PipManager/Controls/Toast.xaml b/src/Controls/Toast.xaml similarity index 79% rename from src/PipManager/Controls/Toast.xaml rename to src/Controls/Toast.xaml index 6c7a2c2..0ab8439 100644 --- a/src/PipManager/Controls/Toast.xaml +++ b/src/Controls/Toast.xaml @@ -1,66 +1,66 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + CornerRadius="5" + HorizontalAlignment="Stretch" + Margin="1" + VerticalAlignment="Stretch"> + VerticalAlignment="Stretch" + x:Name="Grid"> - + + HorizontalAlignment="Left" + Margin="12,0,0,0" + MaxWidth="{Binding TextWidth}" + Text="{Binding Title}" + VerticalAlignment="Center" + x:Name="ToastTitle" /> + HorizontalAlignment="{Binding HorizontalContentAlignment}" + Margin="10,-2,0,0" + Text="{Binding Message}" + VerticalAlignment="Center" + x:Name="ToastMessage" /> diff --git a/src/PipManager/Controls/Toast.xaml.cs b/src/Controls/Toast.xaml.cs similarity index 99% rename from src/PipManager/Controls/Toast.xaml.cs rename to src/Controls/Toast.xaml.cs index ef390b9..14d65dd 100644 --- a/src/PipManager/Controls/Toast.xaml.cs +++ b/src/Controls/Toast.xaml.cs @@ -4,7 +4,7 @@ using Wpf.Ui.Appearance; using Wpf.Ui.Controls; -namespace PipManager.Controls +namespace PipManager.Windows.Controls { public class ToastOptions { diff --git a/src/PipManager/Converters/PackageSourceEnumToBooleanConverter.cs b/src/Converters/PackageSourceEnumToBooleanConverter.cs similarity index 90% rename from src/PipManager/Converters/PackageSourceEnumToBooleanConverter.cs rename to src/Converters/PackageSourceEnumToBooleanConverter.cs index 508cf6c..7bfb28c 100644 --- a/src/PipManager/Converters/PackageSourceEnumToBooleanConverter.cs +++ b/src/Converters/PackageSourceEnumToBooleanConverter.cs @@ -1,8 +1,8 @@ -using PipManager.Models.Package; -using System.Globalization; +using System.Globalization; using System.Windows.Data; +using PipManager.Windows.Models.Package; -namespace PipManager.Converters; +namespace PipManager.Windows.Converters; internal class PackageSourceEnumToBooleanConverter : IValueConverter { diff --git a/src/PipManager/Converters/ThemeEnumToBooleanConverter.cs b/src/Converters/ThemeEnumToBooleanConverter.cs similarity index 96% rename from src/PipManager/Converters/ThemeEnumToBooleanConverter.cs rename to src/Converters/ThemeEnumToBooleanConverter.cs index 4fafbcc..19b7f91 100644 --- a/src/PipManager/Converters/ThemeEnumToBooleanConverter.cs +++ b/src/Converters/ThemeEnumToBooleanConverter.cs @@ -1,7 +1,7 @@ using System.Globalization; using System.Windows.Data; -namespace PipManager.Converters; +namespace PipManager.Windows.Converters; internal class ThemeEnumToBooleanConverter : IValueConverter { diff --git a/src/PipManager/FodyWeavers.xml b/src/FodyWeavers.xml similarity index 100% rename from src/PipManager/FodyWeavers.xml rename to src/FodyWeavers.xml diff --git a/src/PipManager/GlobalUsings.cs b/src/GlobalUsings.cs similarity index 100% rename from src/PipManager/GlobalUsings.cs rename to src/GlobalUsings.cs diff --git a/src/PipManager/Helpers/PackageValidator.cs b/src/Helpers/PackageValidator.cs similarity index 80% rename from src/PipManager/Helpers/PackageValidator.cs rename to src/Helpers/PackageValidator.cs index 0bcebae..c776797 100644 --- a/src/PipManager/Helpers/PackageValidator.cs +++ b/src/Helpers/PackageValidator.cs @@ -1,7 +1,7 @@ -using PipManager.Models.Package; -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; +using PipManager.Windows.Models.Package; -namespace PipManager.Helpers; +namespace PipManager.Windows.Helpers; public static partial class PackageValidator { @@ -27,6 +27,17 @@ public static PackageVersion CheckVersion(string version) return new PackageVersion(); } + + public static bool IsReleaseVersion(string version) + { + var match = VersionRegex().Match(version); + if (match.Success) + { + return string.IsNullOrEmpty(match.Groups["pre_l"].Value) && string.IsNullOrEmpty(match.Groups["post_l"].Value) && string.IsNullOrEmpty(match.Groups["dev_l"].Value); + } + + return false; + } [GeneratedRegex( "^\\s*\r\n v?\r\n (?:\r\n (?:(?[0-9]+)!)?\r\n (?[0-9]+(?:\\.[0-9]+)*)\r\n (?
\r\n                    [-_\\.]?\r\n                    (?(a|b|c|rc|alpha|beta|pre|preview))\r\n                    [-_\\.]?\r\n                    (?[0-9]+)?\r\n                )?\r\n                (?\r\n                    (?:-(?[0-9]+))\r\n                    |\r\n                    (?:\r\n                        [-_\\.]?\r\n                        (?post|rev|r)\r\n                        [-_\\.]?\r\n                        (?[0-9]+)?\r\n                    )\r\n                )?\r\n                (?\r\n                    [-_\\.]?\r\n                    (?dev)\r\n                    [-_\\.]?\r\n                    (?[0-9]+)?\r\n                )?\r\n            )\r\n            (?:\\+(?[a-z0-9]+(?:[-_\\.][a-z0-9]+)*))?\\s*$",
diff --git a/src/PipManager/Helpers/ThreadIdEnricher.cs b/src/Helpers/ThreadIdEnricher.cs
similarity index 89%
rename from src/PipManager/Helpers/ThreadIdEnricher.cs
rename to src/Helpers/ThreadIdEnricher.cs
index 1e3de84..d935a43 100644
--- a/src/PipManager/Helpers/ThreadIdEnricher.cs
+++ b/src/Helpers/ThreadIdEnricher.cs
@@ -1,7 +1,7 @@
 using Serilog.Core;
 using Serilog.Events;
 
-namespace PipManager.Helpers;
+namespace PipManager.Windows.Helpers;
 
 internal class ThreadIdEnricher : ILogEventEnricher
 {
diff --git a/src/PipManager/Languages/GetLanguage.cs b/src/Languages/GetLanguage.cs
similarity index 81%
rename from src/PipManager/Languages/GetLanguage.cs
rename to src/Languages/GetLanguage.cs
index 3cb93f9..679876c 100644
--- a/src/PipManager/Languages/GetLanguage.cs
+++ b/src/Languages/GetLanguage.cs
@@ -1,4 +1,4 @@
-namespace PipManager.Languages;
+namespace PipManager.Windows.Languages;
 
 public static class GetLanguage
 {
diff --git a/src/PipManager/Languages/Lang.Designer.cs b/src/Languages/Lang.Designer.cs
similarity index 95%
rename from src/PipManager/Languages/Lang.Designer.cs
rename to src/Languages/Lang.Designer.cs
index 2a2b18c..176257d 100644
--- a/src/PipManager/Languages/Lang.Designer.cs
+++ b/src/Languages/Lang.Designer.cs
@@ -7,7 +7,7 @@
 // 
 //------------------------------------------------------------------------------
 
-namespace PipManager.Languages {
+namespace PipManager.Windows.Languages {
     using System;
     
     
@@ -38,7 +38,7 @@ internal Lang() {
         public static global::System.Resources.ResourceManager ResourceManager {
             get {
                 if (object.ReferenceEquals(resourceMan, null)) {
-                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PipManager.Languages.Lang", typeof(Lang).Assembly);
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PipManager.Windows.Languages.Lang", typeof(Lang).Assembly);
                     resourceMan = temp;
                 }
                 return resourceMan;
@@ -833,6 +833,15 @@ public static string Library_Data_PackageFound {
             }
         }
         
+        /// 
+        ///   Looks up a localized string similar to {0}s used.
+        /// 
+        public static string Library_Data_RefreshTimeUsage {
+            get {
+                return ResourceManager.GetString("Library_Data_RefreshTimeUsage", resourceCulture);
+            }
+        }
+        
         /// 
         ///   Looks up a localized string similar to {0} item(s) selected.
         /// 
@@ -1139,6 +1148,33 @@ public static string LibraryDetail_Contact_ProjectUrl {
             }
         }
         
+        /// 
+        ///   Looks up a localized string similar to Found {0} dependency packages.
+        /// 
+        public static string LibraryDetail_Dependency_Caption {
+            get {
+                return ResourceManager.GetString("LibraryDetail_Dependency_Caption", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to No dependency packages required.
+        /// 
+        public static string LibraryDetail_Dependency_Empty {
+            get {
+                return ResourceManager.GetString("LibraryDetail_Dependency_Empty", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Dependencies.
+        /// 
+        public static string LibraryDetail_Dependency_Header {
+            get {
+                return ResourceManager.GetString("LibraryDetail_Dependency_Header", resourceCulture);
+            }
+        }
+        
         /// 
         ///   Looks up a localized string similar to Details.
         /// 
@@ -1175,6 +1211,15 @@ public static string LibraryDetail_Summary {
             }
         }
         
+        /// 
+        ///   Looks up a localized string similar to Dependency Not Found.
+        /// 
+        public static string LibraryDetail_Toast_PackageNotFound {
+            get {
+                return ResourceManager.GetString("LibraryDetail_Toast_PackageNotFound", resourceCulture);
+            }
+        }
+        
         /// 
         ///   Looks up a localized string similar to Unknown.
         /// 
@@ -1562,6 +1607,15 @@ public static string SearchDetail_DownloadDistributions {
             }
         }
         
+        /// 
+        ///   Looks up a localized string similar to Network Request Error.
+        /// 
+        public static string SearchDetail_Exception_NetworkError {
+            get {
+                return ResourceManager.GetString("SearchDetail_Exception_NetworkError", resourceCulture);
+            }
+        }
+        
         /// 
         ///   Looks up a localized string similar to Details.
         /// 
@@ -1617,11 +1671,11 @@ public static string Settings_Category_FileManagement {
         }
         
         /// 
-        ///   Looks up a localized string similar to Network.
+        ///   Looks up a localized string similar to Package.
         /// 
-        public static string Settings_Category_Network {
+        public static string Settings_Category_Package {
             get {
-                return ResourceManager.GetString("Settings_Category_Network", resourceCulture);
+                return ResourceManager.GetString("Settings_Category_Package", resourceCulture);
             }
         }
         
@@ -1643,6 +1697,24 @@ public static string Settings_Category_Personalization {
             }
         }
         
+        /// 
+        ///   Looks up a localized string similar to Detecting Test Versions.
+        /// 
+        public static string Settings_DetectNonReleaseVersion {
+            get {
+                return ResourceManager.GetString("Settings_DetectNonReleaseVersion", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Packages that are in Alpha, Beta, etc. test versions will not be ignored.
+        /// 
+        public static string Settings_DetectNonReleaseVersion_Subtitle {
+            get {
+                return ResourceManager.GetString("Settings_DetectNonReleaseVersion_Subtitle", resourceCulture);
+            }
+        }
+        
         /// 
         ///   Looks up a localized string similar to Crushes folder not found.
         /// 
diff --git a/src/PipManager/Languages/Lang.resx b/src/Languages/Lang.resx
similarity index 96%
rename from src/PipManager/Languages/Lang.resx
rename to src/Languages/Lang.resx
index d23e07c..c9ff019 100644
--- a/src/PipManager/Languages/Lang.resx
+++ b/src/Languages/Lang.resx
@@ -675,8 +675,8 @@
   
     Change window theme
   
-  
-    Network
+  
+    Package
   
   
     Set the log file number limit
@@ -744,4 +744,28 @@
   
     Update
   
+  
+    Network Request Error
+  
+  
+    Dependencies
+  
+  
+    No dependency packages required
+  
+  
+    Found {0} dependency packages
+  
+  
+    Detecting Test Versions
+  
+  
+    Packages that are in Alpha, Beta, etc. test versions will not be ignored
+  
+  
+    Dependency Not Found
+  
+  
+    {0}s used
+  
 
\ No newline at end of file
diff --git a/src/PipManager/Languages/Lang.zh-cn.resx b/src/Languages/Lang.zh-cn.resx
similarity index 96%
rename from src/PipManager/Languages/Lang.zh-cn.resx
rename to src/Languages/Lang.zh-cn.resx
index 427f093..6f4b73f 100644
--- a/src/PipManager/Languages/Lang.zh-cn.resx
+++ b/src/Languages/Lang.zh-cn.resx
@@ -675,8 +675,8 @@
   
     设置窗口主题色
   
-  
-    网络
+  
+    
   
   
     设置日志文件数量限制
@@ -744,4 +744,28 @@
   
     更新
   
+  
+    网络请求错误
+  
+  
+    依赖包
+  
+  
+    没有所需的依赖包
+  
+  
+    找到 {0} 个依赖包
+  
+  
+    检测测试版本
+  
+  
+    Alpha、Beta等测试版本的包将不会被忽略
+  
+  
+    未在库中找到该依赖
+  
+  
+    用时 {0} 秒
+  
 
\ No newline at end of file
diff --git a/src/PipManager/Languages/LangKeys.cs b/src/Languages/LangKeys.cs
similarity index 71%
rename from src/PipManager/Languages/LangKeys.cs
rename to src/Languages/LangKeys.cs
index 4c55386..71da21a 100644
--- a/src/PipManager/Languages/LangKeys.cs
+++ b/src/Languages/LangKeys.cs
@@ -1,6 +1,6 @@
 using Antelcat.I18N.Attributes;
 
-namespace PipManager.Languages;
+namespace PipManager.Windows.Languages;
 
 [ResourceKeysOf(typeof(Lang))]
 public partial class LangKeys;
\ No newline at end of file
diff --git a/src/PipManager/Models/Action/ActionListItem.cs b/src/Models/Action/ActionListItem.cs
similarity index 97%
rename from src/PipManager/Models/Action/ActionListItem.cs
rename to src/Models/Action/ActionListItem.cs
index d761006..3f61a23 100644
--- a/src/PipManager/Models/Action/ActionListItem.cs
+++ b/src/Models/Action/ActionListItem.cs
@@ -1,7 +1,7 @@
-using PipManager.Languages;
+using PipManager.Windows.Languages;
 using Wpf.Ui.Controls;
 
-namespace PipManager.Models.Action;
+namespace PipManager.Windows.Models.Action;
 
 public partial class ActionListItem : ObservableObject
 {
diff --git a/src/PipManager/Models/Action/ActionType.cs b/src/Models/Action/ActionType.cs
similarity index 69%
rename from src/PipManager/Models/Action/ActionType.cs
rename to src/Models/Action/ActionType.cs
index 75ae8dc..88e2803 100644
--- a/src/PipManager/Models/Action/ActionType.cs
+++ b/src/Models/Action/ActionType.cs
@@ -1,4 +1,4 @@
-namespace PipManager.Models.Action;
+namespace PipManager.Windows.Models.Action;
 
 public enum ActionType
 {
diff --git a/src/PipManager/Models/AppConfig.cs b/src/Models/AppConfig.cs
similarity index 83%
rename from src/PipManager/Models/AppConfig.cs
rename to src/Models/AppConfig.cs
index ded0761..c0984ba 100644
--- a/src/PipManager/Models/AppConfig.cs
+++ b/src/Models/AppConfig.cs
@@ -1,7 +1,7 @@
 using Newtonsoft.Json;
-using PipManager.Models.AppConfigModels;
+using PipManager.Windows.Models.AppConfigModels;
 
-namespace PipManager.Models;
+namespace PipManager.Windows.Models;
 
 public class AppConfig
 {
diff --git a/src/PipManager/Models/AppConfigModels/EnvironmentItem.cs b/src/Models/AppConfigModels/EnvironmentItem.cs
similarity index 70%
rename from src/PipManager/Models/AppConfigModels/EnvironmentItem.cs
rename to src/Models/AppConfigModels/EnvironmentItem.cs
index 885384e..8eaf886 100644
--- a/src/PipManager/Models/AppConfigModels/EnvironmentItem.cs
+++ b/src/Models/AppConfigModels/EnvironmentItem.cs
@@ -1,6 +1,6 @@
 using Newtonsoft.Json;
 
-namespace PipManager.Models.AppConfigModels;
+namespace PipManager.Windows.Models.AppConfigModels;
 
 public class EnvironmentItem
 {
@@ -8,14 +8,16 @@ public EnvironmentItem()
     {
     }
 
-    public EnvironmentItem(string pipVersion, string pythonPath, string pythonVersion)
+    public EnvironmentItem(string pipVersion, string pythonPath, string pythonVersion, string pythonDllPath)
     {
         PipVersion = pipVersion;
         PythonPath = pythonPath;
         PythonVersion = pythonVersion;
+        PythonDllPath = pythonDllPath;
     }
 
     [JsonProperty("pipVersion")] public string? PipVersion { get; set; }
     [JsonProperty("pythonPath")] public string? PythonPath { get; set; }
     [JsonProperty("pythonVersion")] public string? PythonVersion { get; set; }
+    [JsonProperty("pythonDllPath")] public string? PythonDllPath { get; set; }
 }
\ No newline at end of file
diff --git a/src/Models/AppConfigModels/PackageSource.cs b/src/Models/AppConfigModels/PackageSource.cs
new file mode 100644
index 0000000..e0b45f5
--- /dev/null
+++ b/src/Models/AppConfigModels/PackageSource.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+using PipManager.Windows.Models.Package;
+
+namespace PipManager.Windows.Models.AppConfigModels;
+
+public class PackageSource
+{
+    [JsonProperty("packageSourceType")] public PackageSourceType PackageSourceType { get; set; } = PackageSourceType.Official;
+    [JsonProperty("detectNonReleaseVersion")] public bool DetectNonReleaseVersion { get; set; }
+}
\ No newline at end of file
diff --git a/src/PipManager/Models/AppConfigModels/Personalization.cs b/src/Models/AppConfigModels/Personalization.cs
similarity index 92%
rename from src/PipManager/Models/AppConfigModels/Personalization.cs
rename to src/Models/AppConfigModels/Personalization.cs
index bc822b8..3a21720 100644
--- a/src/PipManager/Models/AppConfigModels/Personalization.cs
+++ b/src/Models/AppConfigModels/Personalization.cs
@@ -1,6 +1,6 @@
 using Newtonsoft.Json;
 
-namespace PipManager.Models.AppConfigModels;
+namespace PipManager.Windows.Models.AppConfigModels;
 
 public class Personalization
 {
diff --git a/src/PipManager/Models/ExceptionType.cs b/src/Models/ExceptionType.cs
similarity index 72%
rename from src/PipManager/Models/ExceptionType.cs
rename to src/Models/ExceptionType.cs
index 6576ccc..5ee98cb 100644
--- a/src/PipManager/Models/ExceptionType.cs
+++ b/src/Models/ExceptionType.cs
@@ -1,4 +1,4 @@
-namespace PipManager.Models;
+namespace PipManager.Windows.Models;
 
 public enum ExceptionType
 {
diff --git a/src/Models/Package/PackageItem.cs b/src/Models/Package/PackageItem.cs
new file mode 100644
index 0000000..47353bb
--- /dev/null
+++ b/src/Models/Package/PackageItem.cs
@@ -0,0 +1,19 @@
+using PipManager.Windows.Models.Pages;
+
+namespace PipManager.Windows.Models.Package;
+
+public class PackageItem
+{
+    public string? Name { get; init; }
+    public string? Version { get; init; }
+    public PackageVersion? DetailedVersion { get; init; }
+    public string? Path { get; init; }
+    public string? DistInfoPath { get; init; }
+    public string? Summary { get; init; }
+    public List? Author { get; init; }
+    public string? AuthorEmail { get; init; }
+    public List? ProjectUrl { get; init; }
+    public Dictionary>? Classifier { get; init; }
+    public Dictionary>? Metadata { get; init; }
+    public List? Record { get; init; }
+}
\ No newline at end of file
diff --git a/src/PipManager/Models/Package/PackageSourceType.cs b/src/Models/Package/PackageSourceType.cs
similarity index 63%
rename from src/PipManager/Models/Package/PackageSourceType.cs
rename to src/Models/Package/PackageSourceType.cs
index 9ccc9ac..8d92342 100644
--- a/src/PipManager/Models/Package/PackageSourceType.cs
+++ b/src/Models/Package/PackageSourceType.cs
@@ -1,4 +1,4 @@
-namespace PipManager.Models.Package;
+namespace PipManager.Windows.Models.Package;
 
 public enum PackageSourceType
 {
diff --git a/src/PipManager/Models/Package/PackageUpdateItem.cs b/src/Models/Package/PackageUpdateItem.cs
similarity index 76%
rename from src/PipManager/Models/Package/PackageUpdateItem.cs
rename to src/Models/Package/PackageUpdateItem.cs
index 4089d3d..218bd7a 100644
--- a/src/PipManager/Models/Package/PackageUpdateItem.cs
+++ b/src/Models/Package/PackageUpdateItem.cs
@@ -1,7 +1,7 @@
-using PipManager.Languages;
-using PipManager.Models.Pages;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models.Pages;
 
-namespace PipManager.Models.Package;
+namespace PipManager.Windows.Models.Package;
 
 public class PackageUpdateItem(LibraryListItem libraryListItem, string newVersion)
 {
diff --git a/src/PipManager/Models/Package/PackageVersion.cs b/src/Models/Package/PackageVersion.cs
similarity index 90%
rename from src/PipManager/Models/Package/PackageVersion.cs
rename to src/Models/Package/PackageVersion.cs
index 9e76a7a..935ef15 100644
--- a/src/PipManager/Models/Package/PackageVersion.cs
+++ b/src/Models/Package/PackageVersion.cs
@@ -1,4 +1,4 @@
-namespace PipManager.Models.Package;
+namespace PipManager.Windows.Models.Package;
 
 public class PackageVersion
 {
diff --git a/src/PipManager/Models/Pages/AboutNugetLibraryListItem.cs b/src/Models/Pages/AboutNugetLibraryListItem.cs
similarity index 89%
rename from src/PipManager/Models/Pages/AboutNugetLibraryListItem.cs
rename to src/Models/Pages/AboutNugetLibraryListItem.cs
index 1d10db4..2a84599 100644
--- a/src/PipManager/Models/Pages/AboutNugetLibraryListItem.cs
+++ b/src/Models/Pages/AboutNugetLibraryListItem.cs
@@ -1,4 +1,4 @@
-namespace PipManager.Models.Pages;
+namespace PipManager.Windows.Models.Pages;
 
 public class AboutNugetLibraryListItem(string libraryName, string libraryLicenseType, string libraryCopyright, string libraryUrl)
 {
diff --git a/src/PipManager/Models/Pages/LibraryDetailProjectUrlModel.cs b/src/Models/Pages/LibraryDetailProjectUrlModel.cs
similarity index 82%
rename from src/PipManager/Models/Pages/LibraryDetailProjectUrlModel.cs
rename to src/Models/Pages/LibraryDetailProjectUrlModel.cs
index c44bb9c..108f0a8 100644
--- a/src/PipManager/Models/Pages/LibraryDetailProjectUrlModel.cs
+++ b/src/Models/Pages/LibraryDetailProjectUrlModel.cs
@@ -1,6 +1,6 @@
 using Wpf.Ui.Controls;
 
-namespace PipManager.Models.Pages;
+namespace PipManager.Windows.Models.Pages;
 
 public class LibraryDetailProjectUrlModel
 {
diff --git a/src/PipManager/Models/Pages/LibraryInstallPackageItem.cs b/src/Models/Pages/LibraryInstallPackageItem.cs
similarity index 87%
rename from src/PipManager/Models/Pages/LibraryInstallPackageItem.cs
rename to src/Models/Pages/LibraryInstallPackageItem.cs
index e1b0ea2..375ce5e 100644
--- a/src/PipManager/Models/Pages/LibraryInstallPackageItem.cs
+++ b/src/Models/Pages/LibraryInstallPackageItem.cs
@@ -1,4 +1,4 @@
-namespace PipManager.Models.Pages;
+namespace PipManager.Windows.Models.Pages;
 
 public class LibraryInstallPackageItem
 {
diff --git a/src/PipManager/Models/Pages/LibraryListItem.cs b/src/Models/Pages/LibraryListItem.cs
similarity index 87%
rename from src/PipManager/Models/Pages/LibraryListItem.cs
rename to src/Models/Pages/LibraryListItem.cs
index 8bf0e8b..4b3b6f4 100644
--- a/src/PipManager/Models/Pages/LibraryListItem.cs
+++ b/src/Models/Pages/LibraryListItem.cs
@@ -1,7 +1,7 @@
-using PipManager.Models.Package;
+using PipManager.Windows.Models.Package;
 using Wpf.Ui.Controls;
 
-namespace PipManager.Models.Pages;
+namespace PipManager.Windows.Models.Pages;
 
 public class LibraryListItem(
     SymbolIcon icon,
diff --git a/src/PipManager/Models/Pypi/PypiPackageInfo.cs b/src/Models/Pypi/PypiPackageInfo.cs
similarity index 93%
rename from src/PipManager/Models/Pypi/PypiPackageInfo.cs
rename to src/Models/Pypi/PypiPackageInfo.cs
index 7607c97..b7d96d0 100644
--- a/src/PipManager/Models/Pypi/PypiPackageInfo.cs
+++ b/src/Models/Pypi/PypiPackageInfo.cs
@@ -1,6 +1,6 @@
 using Newtonsoft.Json;
 
-namespace PipManager.Models.Pypi;
+namespace PipManager.Windows.Models.Pypi;
 
 public class PypiPackageInfo
 {
diff --git a/src/PipManager.PackageSearch/IPackageSearchService.cs b/src/PipManager.PackageSearch/IPackageSearchService.cs
deleted file mode 100644
index a341b2d..0000000
--- a/src/PipManager.PackageSearch/IPackageSearchService.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using PipManager.PackageSearch.Wrappers.Query;
-
-namespace PipManager.PackageSearch;
-
-public interface IPackageSearchService
-{
-    public Task Query(string name, int page = 1);
-}
\ No newline at end of file
diff --git a/src/PipManager.PackageSearch/PackageSearchService.cs b/src/PipManager.PackageSearch/PackageSearchService.cs
deleted file mode 100644
index 4fffcaf..0000000
--- a/src/PipManager.PackageSearch/PackageSearchService.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-using HtmlAgilityPack;
-using PipManager.PackageSearch.Wrappers.Query;
-
-namespace PipManager.PackageSearch;
-
-public class PackageSearchService(HttpClient httpClient) : IPackageSearchService
-{
-    private Dictionary<(string, int), QueryWrapper> QueryCaches { get; } = [];
-
-    public async Task Query(string name, int page = 1)
-    {
-        if (QueryCaches.ContainsKey((name, page)))
-        {
-            return QueryCaches[(name, page)];
-        }
-        string htmlContent;
-        try
-        {
-            htmlContent = await httpClient.GetStringAsync($"https://pypi.org/search/?q={name}&page={page}");
-        }
-        catch (Exception exception) when (exception is TaskCanceledException or HttpRequestException)
-        {
-            return new QueryWrapper
-            {
-                Status = QueryStatus.Timeout
-            };
-        }
-        var htmlDocument = new HtmlDocument();
-        htmlDocument.LoadHtml(htmlContent);
-
-        var queryWrapper = new QueryWrapper
-        {
-            ResultCount = htmlDocument.DocumentNode.SelectSingleNode("/html/body/main/div/div/div[2]/form/div[1]/div[1]/p/strong").InnerText
-        };
-        queryWrapper.Status = queryWrapper.ResultCount != "0" ? QueryStatus.Success : QueryStatus.NoResults;
-        if (queryWrapper.Status == QueryStatus.NoResults)
-        {
-            return queryWrapper;
-        }
-        var pageNode = htmlDocument.DocumentNode.SelectSingleNode("/html/body/main/div/div/div[2]/form/div[3]/div");
-        queryWrapper.MaxPageNumber = pageNode == null ? 1 : int.Parse(pageNode.ChildNodes[^4].InnerText);
-
-        try
-        {
-            var resultList = htmlDocument.DocumentNode.SelectSingleNode("/html/body/main/div/div/div[2]/form/div[3]/ul").ChildNodes.Where(result => result.InnerLength != 15).Select(result => result.ChildNodes[1]);
-            queryWrapper.Results = [];
-            foreach (var resultItem in resultList)
-            {
-                queryWrapper.Results.Add(new QueryListItemModel
-                {
-                    Name = resultItem.ChildNodes[1].ChildNodes[1].InnerText,
-                    Version = resultItem.ChildNodes[1].ChildNodes[3].InnerText,
-                    Description = resultItem.ChildNodes[3].InnerText,
-                    Url = $"https://pypi.org{resultItem.Attributes["href"].Value}",
-                    // ReSharper disable once StringLiteralTypo
-                    UpdateTime = DateTime.ParseExact(resultItem.ChildNodes[1].ChildNodes[5].ChildNodes[0].Attributes["datetime"].Value, "yyyy-MM-ddTHH:mm:sszzz", null, System.Globalization.DateTimeStyles.RoundtripKind)
-                });
-            }
-        }
-        catch (ArgumentOutOfRangeException)
-        {
-            QueryCaches.Add((name, page), queryWrapper);
-            return queryWrapper;
-        }
-        QueryCaches.Add((name, page), queryWrapper);
-        return queryWrapper;
-    }
-}
\ No newline at end of file
diff --git a/src/PipManager.PackageSearch/PipManager.PackageSearch.csproj b/src/PipManager.PackageSearch/PipManager.PackageSearch.csproj
deleted file mode 100644
index 2523916..0000000
--- a/src/PipManager.PackageSearch/PipManager.PackageSearch.csproj
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-  
-    net8.0
-    enable
-    enable
-	embedded
-	true
-  
-
-  
-  
-
-  
-	true
-	Speed
-    false
-	true
-  
-
-  
-    
-    
-  
-
-
diff --git a/src/PipManager.PackageSearch/Wrappers/Query/QueryListItemModel.cs b/src/PipManager.PackageSearch/Wrappers/Query/QueryListItemModel.cs
deleted file mode 100644
index 0a077c5..0000000
--- a/src/PipManager.PackageSearch/Wrappers/Query/QueryListItemModel.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace PipManager.PackageSearch.Wrappers.Query;
-
-public class QueryListItemModel
-{
-    public required string Name { get; set; }
-    public required string Version { get; set; }
-    public required string Description { get; set; }
-    public required string Url { get; set; }
-    public DateTime UpdateTime { get; set; }
-}
\ No newline at end of file
diff --git a/src/PipManager.PackageSearch/Wrappers/Query/QueryStatus.cs b/src/PipManager.PackageSearch/Wrappers/Query/QueryStatus.cs
deleted file mode 100644
index aaacee6..0000000
--- a/src/PipManager.PackageSearch/Wrappers/Query/QueryStatus.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace PipManager.PackageSearch.Wrappers.Query;
-
-public enum QueryStatus
-{
-    Success,
-    NoResults,
-    Timeout
-}
\ No newline at end of file
diff --git a/src/PipManager.PackageSearch/Wrappers/Query/QueryWrapper.cs b/src/PipManager.PackageSearch/Wrappers/Query/QueryWrapper.cs
deleted file mode 100644
index dc1c845..0000000
--- a/src/PipManager.PackageSearch/Wrappers/Query/QueryWrapper.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace PipManager.PackageSearch.Wrappers.Query;
-
-public class QueryWrapper
-{
-    public QueryStatus Status { get; set; }
-    public string? ResultCount { get; set; }
-    public List? Results { get; set; }
-    public int MaxPageNumber { get; set; }
-}
\ No newline at end of file
diff --git a/src/PipManager/PipManager.csproj b/src/PipManager.Windows.csproj
similarity index 88%
rename from src/PipManager/PipManager.csproj
rename to src/PipManager.Windows.csproj
index 0ef5769..f6f1c44 100644
--- a/src/PipManager/PipManager.csproj
+++ b/src/PipManager.Windows.csproj
@@ -29,19 +29,19 @@
 	
 		
 		
-		
-		
+		
+		
 		
-		
+		
 		
-		
-		
+		
+		
 		
 		
-		
+		
 		
 		
-		
+		
 		
 	
 
@@ -101,6 +101,6 @@
 	
 
 	
-	  
+	  
 	
 
diff --git a/src/PipManager.sln b/src/PipManager.sln
deleted file mode 100644
index dee2b6d..0000000
--- a/src/PipManager.sln
+++ /dev/null
@@ -1,36 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.7.34024.191
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PipManager", "PipManager\PipManager.csproj", "{4C085660-9DCE-403F-89A7-E36C9405BBC0}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "解决方案项", "解决方案项", "{B7B16EC6-9787-477B-B84A-7DACBEB96277}"
-	ProjectSection(SolutionItems) = preProject
-		..\README.md = ..\README.md
-	EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PipManager.PackageSearch", "PipManager.PackageSearch\PipManager.PackageSearch.csproj", "{759DBA08-4418-474E-BD6F-773829A81368}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{4C085660-9DCE-403F-89A7-E36C9405BBC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{4C085660-9DCE-403F-89A7-E36C9405BBC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{4C085660-9DCE-403F-89A7-E36C9405BBC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{4C085660-9DCE-403F-89A7-E36C9405BBC0}.Release|Any CPU.Build.0 = Release|Any CPU
-		{759DBA08-4418-474E-BD6F-773829A81368}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{759DBA08-4418-474E-BD6F-773829A81368}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{759DBA08-4418-474E-BD6F-773829A81368}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{759DBA08-4418-474E-BD6F-773829A81368}.Release|Any CPU.Build.0 = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-	GlobalSection(ExtensibilityGlobals) = postSolution
-		SolutionGuid = {B6F6718F-A5F4-4FD9-8238-BD20B7983304}
-	EndGlobalSection
-EndGlobal
diff --git a/src/PipManager/Models/AppConfigModels/PackageSource.cs b/src/PipManager/Models/AppConfigModels/PackageSource.cs
deleted file mode 100644
index a0c462c..0000000
--- a/src/PipManager/Models/AppConfigModels/PackageSource.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Newtonsoft.Json;
-using PipManager.Models.Package;
-
-namespace PipManager.Models.AppConfigModels;
-
-public class PackageSource
-{
-    [JsonProperty("packageSourceType")] public PackageSourceType PackageSourceType { get; set; } = PackageSourceType.Official;
-}
\ No newline at end of file
diff --git a/src/PipManager/Models/Package/PackageItem.cs b/src/PipManager/Models/Package/PackageItem.cs
deleted file mode 100644
index d527f36..0000000
--- a/src/PipManager/Models/Package/PackageItem.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using PipManager.Models.Pages;
-
-namespace PipManager.Models.Package;
-
-public class PackageItem
-{
-    public string? Name { get; set; }
-    public string? Version { get; set; }
-    public PackageVersion? DetailedVersion { get; set; }
-    public string? Path { get; set; }
-    public string? DistInfoPath { get; set; }
-    public string? Summary { get; set; }
-    public List? Author { get; set; }
-    public string? AuthorEmail { get; set; }
-    public List? ProjectUrl { get; set; }
-    public Dictionary>? Classifier { get; set; }
-    public Dictionary>? Metadata { get; set; }
-    public List? Record { get; set; }
-}
\ No newline at end of file
diff --git a/src/PipManager/ViewModels/Pages/Overlay/OverlayViewModel.cs b/src/PipManager/ViewModels/Pages/Overlay/OverlayViewModel.cs
deleted file mode 100644
index fcfc453..0000000
--- a/src/PipManager/ViewModels/Pages/Overlay/OverlayViewModel.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System.Collections.ObjectModel;
-using PipManager.Models.Package;
-using PipManager.Views.Windows;
-
-namespace PipManager.ViewModels.Pages.Overlay;
-
-public partial class OverlayViewModel: ObservableObject
-{
-    private System.Action? _confirmCallback;
-    
-    [ObservableProperty]
-    private bool _isOverlayVisible;
-    
-    [RelayCommand]
-    private void CloseOverlay()
-    {
-        IsOverlayVisible = false;
-        App.GetService().TitleBarCoverageGrid.Visibility = Visibility.Collapsed;
-    }
-    
-    private void ShowOverlay()
-    {
-        IsOverlayVisible = true;
-        App.GetService().TitleBarCoverageGrid.Visibility = Visibility.Visible;
-    }
-
-    [ObservableProperty] private ObservableCollection _packageUpdateItems = [];
-
-    public void ShowPackageUpdateOverlay(List packageUpdates, System.Action callback)
-    {
-        _confirmCallback = callback;
-        PackageUpdateItems = new ObservableCollection(packageUpdates);
-        ShowOverlay();
-    }
-
-    [RelayCommand]
-    private void Confirm()
-    {
-        CloseOverlay();
-        _confirmCallback?.Invoke();
-    }
-}
diff --git a/src/PipManager/Views/Pages/About/AboutPage.xaml.cs b/src/PipManager/Views/Pages/About/AboutPage.xaml.cs
deleted file mode 100644
index 218b79b..0000000
--- a/src/PipManager/Views/Pages/About/AboutPage.xaml.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Wpf.Ui.Controls;
-using AboutViewModel = PipManager.ViewModels.Pages.About.AboutViewModel;
-
-namespace PipManager.Views.Pages.About;
-
-public partial class AboutPage : INavigableView
-{
-    public AboutViewModel ViewModel { get; }
-
-    public AboutPage(AboutViewModel viewModel)
-    {
-        ViewModel = viewModel;
-        DataContext = this;
-
-        InitializeComponent();
-    }
-}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Action/ActionExceptionPage.xaml.cs b/src/PipManager/Views/Pages/Action/ActionExceptionPage.xaml.cs
deleted file mode 100644
index 9388785..0000000
--- a/src/PipManager/Views/Pages/Action/ActionExceptionPage.xaml.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Wpf.Ui.Controls;
-using ActionExceptionViewModel = PipManager.ViewModels.Pages.Action.ActionExceptionViewModel;
-
-namespace PipManager.Views.Pages.Action;
-
-public partial class ActionExceptionPage : INavigableView
-{
-    public ActionExceptionViewModel ViewModel { get; }
-
-    public ActionExceptionPage(ActionExceptionViewModel viewModel)
-    {
-        ViewModel = viewModel;
-        DataContext = this;
-
-        InitializeComponent();
-    }
-}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Action/ActionPage.xaml.cs b/src/PipManager/Views/Pages/Action/ActionPage.xaml.cs
deleted file mode 100644
index 6d1158a..0000000
--- a/src/PipManager/Views/Pages/Action/ActionPage.xaml.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Wpf.Ui.Controls;
-using ActionViewModel = PipManager.ViewModels.Pages.Action.ActionViewModel;
-
-namespace PipManager.Views.Pages.Action;
-
-public partial class ActionPage : INavigableView
-{
-    public ActionViewModel ViewModel { get; }
-
-    public ActionPage(ActionViewModel viewModel)
-    {
-        ViewModel = viewModel;
-        DataContext = this;
-
-        InitializeComponent();
-    }
-}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Environment/EnvironmentPage.xaml b/src/PipManager/Views/Pages/Environment/EnvironmentPage.xaml
deleted file mode 100644
index 46fd731..0000000
--- a/src/PipManager/Views/Pages/Environment/EnvironmentPage.xaml
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-    
-        
-            
-            
-            
-            
-            
-        
-        
-            
-                
-                    
-                        
-                            
-                            
-                            
-                        
-                        
-                        
-                            
-                                
-                                
-                                
-                            
-
-                            
-                        
-                    
-                
-            
-        
-    
-
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Environment/EnvironmentPage.xaml.cs b/src/PipManager/Views/Pages/Environment/EnvironmentPage.xaml.cs
deleted file mode 100644
index 9a9c50c..0000000
--- a/src/PipManager/Views/Pages/Environment/EnvironmentPage.xaml.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Wpf.Ui.Controls;
-using EnvironmentViewModel = PipManager.ViewModels.Pages.Environment.EnvironmentViewModel;
-
-namespace PipManager.Views.Pages.Environment;
-
-public partial class EnvironmentPage : INavigableView
-{
-    public EnvironmentViewModel ViewModel { get; }
-
-    public EnvironmentPage(EnvironmentViewModel viewModel)
-    {
-        ViewModel = viewModel;
-        DataContext = this;
-
-        InitializeComponent();
-    }
-}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Library/LibraryDetailPage.xaml.cs b/src/PipManager/Views/Pages/Library/LibraryDetailPage.xaml.cs
deleted file mode 100644
index de12f54..0000000
--- a/src/PipManager/Views/Pages/Library/LibraryDetailPage.xaml.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Wpf.Ui.Controls;
-using LibraryDetailViewModel = PipManager.ViewModels.Pages.Library.LibraryDetailViewModel;
-
-namespace PipManager.Views.Pages.Library;
-
-public partial class LibraryDetailPage : INavigableView
-{
-    public LibraryDetailViewModel ViewModel { get; }
-
-    public LibraryDetailPage(LibraryDetailViewModel viewModel)
-    {
-        ViewModel = viewModel;
-        DataContext = this;
-        InitializeComponent();
-    }
-}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Library/LibraryInstallPage.xaml.cs b/src/PipManager/Views/Pages/Library/LibraryInstallPage.xaml.cs
deleted file mode 100644
index 5e9992c..0000000
--- a/src/PipManager/Views/Pages/Library/LibraryInstallPage.xaml.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Wpf.Ui.Controls;
-using LibraryInstallViewModel = PipManager.ViewModels.Pages.Library.LibraryInstallViewModel;
-
-namespace PipManager.Views.Pages.Library;
-
-public partial class LibraryInstallPage : INavigableView
-{
-    public LibraryInstallViewModel ViewModel { get; }
-
-    public LibraryInstallPage(LibraryInstallViewModel viewModel)
-    {
-        ViewModel = viewModel;
-        DataContext = this;
-        InitializeComponent();
-    }
-}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Library/LibraryPage.xaml.cs b/src/PipManager/Views/Pages/Library/LibraryPage.xaml.cs
deleted file mode 100644
index 9110cb4..0000000
--- a/src/PipManager/Views/Pages/Library/LibraryPage.xaml.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Wpf.Ui.Controls;
-using LibraryViewModel = PipManager.ViewModels.Pages.Library.LibraryViewModel;
-
-namespace PipManager.Views.Pages.Library;
-
-public partial class LibraryPage : INavigableView
-{
-    public LibraryViewModel ViewModel { get; }
-
-    public LibraryPage(LibraryViewModel viewModel)
-    {
-        ViewModel = viewModel;
-        DataContext = this;
-        InitializeComponent();
-    }
-}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Overlay/OverlayPage.xaml b/src/PipManager/Views/Pages/Overlay/OverlayPage.xaml
deleted file mode 100644
index 5a334d4..0000000
--- a/src/PipManager/Views/Pages/Overlay/OverlayPage.xaml
+++ /dev/null
@@ -1,57 +0,0 @@
-
-    
-        
-            
-            
-            
-        
-        
-        
-            
-                
-                    
-                        
-                            
-                                
-                                
-                                
-                            
-                            
-                            
-                                
-                                
-                                
-                            
-                        
-                    
-                
-            
-        
-        
-            
-            
-        
-    
-
diff --git a/src/PipManager/Views/Pages/Settings/SettingsPage.xaml.cs b/src/PipManager/Views/Pages/Settings/SettingsPage.xaml.cs
deleted file mode 100644
index 229e8cc..0000000
--- a/src/PipManager/Views/Pages/Settings/SettingsPage.xaml.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Wpf.Ui.Controls;
-using SettingsViewModel = PipManager.ViewModels.Pages.Settings.SettingsViewModel;
-
-namespace PipManager.Views.Pages.Settings;
-
-public partial class SettingsPage : INavigableView
-{
-    public SettingsViewModel ViewModel { get; }
-
-    public SettingsPage(SettingsViewModel viewModel)
-    {
-        ViewModel = viewModel;
-        DataContext = this;
-
-        InitializeComponent();
-    }
-}
\ No newline at end of file
diff --git a/src/PipManager/Properties/launchSettings.json b/src/Properties/launchSettings.json
similarity index 100%
rename from src/PipManager/Properties/launchSettings.json
rename to src/Properties/launchSettings.json
diff --git a/src/PipManager/Resources/Animations.xaml b/src/Resources/Animations.xaml
similarity index 100%
rename from src/PipManager/Resources/Animations.xaml
rename to src/Resources/Animations.xaml
diff --git a/src/PipManager/Resources/FluentDesignComplements.xaml b/src/Resources/FluentDesignComplements.xaml
similarity index 100%
rename from src/PipManager/Resources/FluentDesignComplements.xaml
rename to src/Resources/FluentDesignComplements.xaml
diff --git a/src/PipManager/Resources/Fonts/MiSans-Regular.ttf b/src/Resources/Fonts/MiSans-Regular.ttf
similarity index 100%
rename from src/PipManager/Resources/Fonts/MiSans-Regular.ttf
rename to src/Resources/Fonts/MiSans-Regular.ttf
diff --git a/src/PipManager/Resources/Library/DeletionWarningContentDialog.cs b/src/Resources/Library/DeletionWarningContentDialog.cs
similarity index 86%
rename from src/PipManager/Resources/Library/DeletionWarningContentDialog.cs
rename to src/Resources/Library/DeletionWarningContentDialog.cs
index 78045f7..694c068 100644
--- a/src/PipManager/Resources/Library/DeletionWarningContentDialog.cs
+++ b/src/Resources/Library/DeletionWarningContentDialog.cs
@@ -1,9 +1,9 @@
-using PipManager.Languages;
-using PipManager.Models.Pages;
-using System.Windows.Controls;
+using System.Windows.Controls;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models.Pages;
 using Wpf.Ui.Controls;
 
-namespace PipManager.Resources.Library;
+namespace PipManager.Windows.Resources.Library;
 
 public class DeletionWarningContentDialog
 {
diff --git a/src/PipManager/Resources/Library/InstallAddContentDialog.cs b/src/Resources/Library/InstallAddContentDialog.cs
similarity index 88%
rename from src/PipManager/Resources/Library/InstallAddContentDialog.cs
rename to src/Resources/Library/InstallAddContentDialog.cs
index 44b7ed1..e381503 100644
--- a/src/PipManager/Resources/Library/InstallAddContentDialog.cs
+++ b/src/Resources/Library/InstallAddContentDialog.cs
@@ -1,9 +1,9 @@
-using PipManager.Languages;
-using System.Windows.Controls;
+using System.Windows.Controls;
+using PipManager.Windows.Languages;
 using Wpf.Ui.Controls;
 using TextBox = System.Windows.Controls.TextBox;
 
-namespace PipManager.Resources.Library;
+namespace PipManager.Windows.Resources.Library;
 
 public class InstallAddContentDialog(ContentPresenter? contentPresenter)
 {
diff --git a/src/PipManager/Resources/Library/LibraryStyles.xaml b/src/Resources/Library/LibraryStyles.xaml
similarity index 75%
rename from src/PipManager/Resources/Library/LibraryStyles.xaml
rename to src/Resources/Library/LibraryStyles.xaml
index beac0a6..68a5cfb 100644
--- a/src/PipManager/Resources/Library/LibraryStyles.xaml
+++ b/src/Resources/Library/LibraryStyles.xaml
@@ -1,14 +1,14 @@
 
-    
+    xmlns:lang="clr-namespace:PipManager.Windows.Languages"
+    xmlns:pages="clr-namespace:PipManager.Windows.Models.Pages"
+    xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+    
         
+            Text="{I18N {x:Static lang:LangKeys.ContentDialog_Message_LibraryDeletionWarning}}"
+            VerticalAlignment="Top" />
         
             
                 
@@ -17,9 +17,9 @@
                             
                                 
                                     
+                                        Text="{Binding PackageName}"
+                                        VerticalAlignment="Center" />
                                     
                                     
 
     
+        VerticalAlignment="Top"
+        x:Key="LibraryInstallAddContentDialogContent">
         
+            Text="{I18N {x:Static lang:LangKeys.LibraryInstall_Add_Notice}}"
+            VerticalAlignment="Top" />
         
     
 
\ No newline at end of file
diff --git a/src/PipManager/Services/Action/ActionService.cs b/src/Services/Action/ActionService.cs
similarity index 97%
rename from src/PipManager/Services/Action/ActionService.cs
rename to src/Services/Action/ActionService.cs
index def5b2a..c5a12c9 100644
--- a/src/PipManager/Services/Action/ActionService.cs
+++ b/src/Services/Action/ActionService.cs
@@ -1,14 +1,14 @@
-using PipManager.Languages;
-using PipManager.Models.Action;
-using PipManager.Services.Environment;
-using PipManager.Services.Toast;
-using Serilog;
+using Serilog;
 using System.Collections.ObjectModel;
 using System.IO;
 using System.Text;
 using Meziantou.Framework.WPF.Collections;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models.Action;
+using PipManager.Windows.Services.Environment;
+using PipManager.Windows.Services.Toast;
 
-namespace PipManager.Services.Action;
+namespace PipManager.Windows.Services.Action;
 
 public class ActionService(IEnvironmentService environmentService, IToastService toastService)
     : IActionService
diff --git a/src/PipManager/Services/Action/IActionService.cs b/src/Services/Action/IActionService.cs
similarity index 83%
rename from src/PipManager/Services/Action/IActionService.cs
rename to src/Services/Action/IActionService.cs
index a2c7337..01b8a6f 100644
--- a/src/PipManager/Services/Action/IActionService.cs
+++ b/src/Services/Action/IActionService.cs
@@ -1,8 +1,8 @@
 using Meziantou.Framework.WPF.Collections;
-using PipManager.Models.Action;
 using System.Collections.ObjectModel;
+using PipManager.Windows.Models.Action;
 
-namespace PipManager.Services.Action;
+namespace PipManager.Windows.Services.Action;
 
 public interface IActionService
 {
diff --git a/src/PipManager/Services/ApplicationHostService.cs b/src/Services/ApplicationHostService.cs
similarity index 92%
rename from src/PipManager/Services/ApplicationHostService.cs
rename to src/Services/ApplicationHostService.cs
index 3844fed..1bad7d9 100644
--- a/src/PipManager/Services/ApplicationHostService.cs
+++ b/src/Services/ApplicationHostService.cs
@@ -1,9 +1,9 @@
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Hosting;
-using PipManager.Views.Pages.Library;
-using PipManager.Views.Windows;
+using PipManager.Windows.Views.Pages.Library;
+using PipManager.Windows.Views.Windows;
 
-namespace PipManager.Services;
+namespace PipManager.Windows.Services;
 
 /// 
 /// Managed host of the application.
diff --git a/src/PipManager/Services/Configuration/ConfigurationService.cs b/src/Services/Configuration/ConfigurationService.cs
similarity index 86%
rename from src/PipManager/Services/Configuration/ConfigurationService.cs
rename to src/Services/Configuration/ConfigurationService.cs
index bcd9d23..095c909 100644
--- a/src/PipManager/Services/Configuration/ConfigurationService.cs
+++ b/src/Services/Configuration/ConfigurationService.cs
@@ -1,12 +1,12 @@
 using Newtonsoft.Json;
-using PipManager.Models;
-using PipManager.Models.AppConfigModels;
-using PipManager.Models.Package;
 using System.Diagnostics;
 using System.IO;
 using System.Text.RegularExpressions;
+using PipManager.Windows.Models;
+using PipManager.Windows.Models.AppConfigModels;
+using PipManager.Windows.Models.Package;
 
-namespace PipManager.Services.Configuration;
+namespace PipManager.Windows.Services.Configuration;
 
 public partial class ConfigurationService : IConfigurationService
 {
@@ -73,16 +73,17 @@ public string FindPythonPathByPipDir(string pipDir)
     public EnvironmentItem? GetEnvironmentItem(string pythonPath)
     {
         var pythonVersion = FileVersionInfo.GetVersionInfo(pythonPath).FileVersion!;
-        var pythonDirectory = Directory.GetParent(pythonPath)!.FullName;
-        var pipDirectory = GetPipDirectories(pythonDirectory);
-
-        if (pipDirectory == null)
+        var pythonDirectory = Directory.GetParent(pythonPath)!;
+        var pipDirectory = GetPipDirectories(pythonDirectory.FullName);
+        var pythonDllName = $"{pythonDirectory.Name.ToLower().Replace(".", "")}.dll";
+        var pythonDllPath = pythonDirectory.GetFiles(pythonDllName, SearchOption.AllDirectories).FirstOrDefault();
+        if (pythonDllPath == null || pipDirectory == null)
         {
             return null;
         }
 
         var pipVersion = GetPipVersionInInitFile().Match(File.ReadAllText(Path.Combine(pipDirectory, @"__init__.py"))).Groups[1].Value;
-        return new EnvironmentItem(pipVersion, pythonPath, pythonVersion);
+        return new EnvironmentItem(pipVersion, pythonPath, pythonVersion, pythonDllPath.FullName);
     }
 
     public EnvironmentItem? GetEnvironmentItemFromCommand(string command, string arguments)
@@ -137,9 +138,12 @@ public string FindPythonPathByPipDir(string pipDir)
         }
         pipVersion = pipVersion.Trim();
         var pythonPath = FindPythonPathByPipDir(pipDir.Trim());
+        var pythonDirectory = Directory.GetParent(pythonPath)!;
+        var pythonDllName = $"{pythonDirectory.Name.ToLower().Replace(".", "")}.dll";
+        var pythonDllPath = pythonDirectory.GetFiles(pythonDllName, SearchOption.AllDirectories).FirstOrDefault();
         pythonVersion = pythonVersion.Trim();
         proc.Close();
-        return pipDir.Length > 0 ? new EnvironmentItem(pipVersion, pythonPath, pythonVersion) : null;
+        return pipDir.Length > 0 && pythonDllPath != null ? new EnvironmentItem(pipVersion, pythonPath, pythonVersion, pythonDllPath.FullName) : null;
     }
 
     public void RefreshAllEnvironmentVersions()
diff --git a/src/PipManager/Services/Configuration/IConfigurationService.cs b/src/Services/Configuration/IConfigurationService.cs
similarity index 77%
rename from src/PipManager/Services/Configuration/IConfigurationService.cs
rename to src/Services/Configuration/IConfigurationService.cs
index f16260e..354d647 100644
--- a/src/PipManager/Services/Configuration/IConfigurationService.cs
+++ b/src/Services/Configuration/IConfigurationService.cs
@@ -1,8 +1,8 @@
-using PipManager.Models;
-using PipManager.Models.AppConfigModels;
-using PipManager.Models.Package;
+using PipManager.Windows.Models;
+using PipManager.Windows.Models.AppConfigModels;
+using PipManager.Windows.Models.Package;
 
-namespace PipManager.Services.Configuration;
+namespace PipManager.Windows.Services.Configuration;
 
 public interface IConfigurationService
 {
diff --git a/src/PipManager/Services/Environment/EnvironmentService.cs b/src/Services/Environment/EnvironmentService.cs
similarity index 80%
rename from src/PipManager/Services/Environment/EnvironmentService.cs
rename to src/Services/Environment/EnvironmentService.cs
index 262e313..911f71e 100644
--- a/src/PipManager/Services/Environment/EnvironmentService.cs
+++ b/src/Services/Environment/EnvironmentService.cs
@@ -1,22 +1,23 @@
 using Newtonsoft.Json;
-using PipManager.Helpers;
-using PipManager.Models;
-using PipManager.Models.AppConfigModels;
-using PipManager.Models.Package;
-using PipManager.Models.Pages;
-using PipManager.Models.Pypi;
-using PipManager.Services.Configuration;
-using PipManager.Services.Environment.Response;
 using Serilog;
 using System.Collections.Concurrent;
 using System.Diagnostics;
 using System.IO;
 using System.Net.Http;
+using System.Text;
 using System.Text.RegularExpressions;
+using PipManager.Windows.Helpers;
+using PipManager.Windows.Models;
+using PipManager.Windows.Models.AppConfigModels;
+using PipManager.Windows.Models.Package;
+using PipManager.Windows.Models.Pages;
+using PipManager.Windows.Models.Pypi;
+using PipManager.Windows.Services.Configuration;
+using PipManager.Windows.Services.Environment.Response;
 using Wpf.Ui.Controls;
 using Path = System.IO.Path;
 
-namespace PipManager.Services.Environment;
+namespace PipManager.Windows.Services.Environment;
 
 public partial class EnvironmentService(IConfigurationService configurationService) : IEnvironmentService
 {
@@ -93,9 +94,9 @@ public ActionResponse PurgeEnvironmentCache(EnvironmentItem environmentItem)
                 if (packageName == "pip") return;
 
                 // Metadata
-                var metadataDict = new Dictionary>();
+                var metadataDict = new Dictionary>();
                 var lastValidKey = "";
-                var lastValidPos = 0;
+                var lastValidIndex = 0;
                 var classifiers = new Dictionary>();
                 await foreach (var line in File.ReadLinesAsync(Path.Combine(distInfoDirectoryFullName, "METADATA")))
                 {
@@ -113,38 +114,43 @@ public ActionResponse PurgeEnvironmentCache(EnvironmentItem environmentItem)
                         {
                             metadataDict.Add(key, []);
                             lastValidKey = key;
-                            lastValidPos = 0;
+                            lastValidIndex = 0;
                         }
                         else
                         {
-                            lastValidPos++;
+                            lastValidIndex++;
                         }
 
-                        metadataDict[key].Add(value);
+                        metadataDict[key].Add(new StringBuilder(value));
                     }
                     else
                     {
-                        metadataDict[lastValidKey][lastValidPos] = string.Join(metadataDict[lastValidKey][lastValidPos], "\n", value);
+                        metadataDict[lastValidKey][lastValidIndex].Append('\n').Append(value);
                     }
                 }
-
-                foreach (var item in metadataDict.GetValueOrDefault("classifier", []))
+                var metadata = metadataDict.ToDictionary(
+                    pair => pair.Key, 
+                    pair => pair.Value.Select(sb => sb.ToString()).ToList()
+                );
+                foreach (var item in metadata.GetValueOrDefault("classifier", []))
                 {
                     var keyValues = item.Split(" :: ");
 
-                    if (keyValues.Length >= 2)
+                    if (keyValues.Length < 2)
                     {
-                        var key = keyValues[0];
-                        var value = string.Join(" :: ", keyValues[1..]);
+                        continue;
+                    }
 
-                        if (!classifiers.TryGetValue(key, out var existingList))
-                        {
-                            existingList = [];
-                            classifiers.Add(key, existingList);
-                        }
+                    var key = keyValues[0];
+                    var value = string.Join(" :: ", keyValues[1..]);
 
-                        existingList.Add(value);
+                    if (!classifiers.TryGetValue(key, out var existingList))
+                    {
+                        existingList = [];
+                        classifiers.Add(key, existingList);
                     }
+
+                    existingList.Add(value);
                 }
 
                 // Record
@@ -162,7 +168,7 @@ public ActionResponse PurgeEnvironmentCache(EnvironmentItem environmentItem)
                 }
 
                 // Extra
-                var projectUrl = metadataDict.GetValueOrDefault("project-url", []);
+                var projectUrl = metadata.GetValueOrDefault("project-url", []);
                 var projectUrlDictionary = new List();
 
                 if (projectUrl.Count != 0)
@@ -199,6 +205,8 @@ public ActionResponse PurgeEnvironmentCache(EnvironmentItem environmentItem)
                         Url = ""
                     });
                 }
+
+                
                 packages.Add(new PackageItem
                 {
                     Name = packageName,
@@ -206,12 +214,12 @@ public ActionResponse PurgeEnvironmentCache(EnvironmentItem environmentItem)
                     DetailedVersion = PackageValidator.CheckVersion(packageVersion),
                     Path = actualPath,
                     DistInfoPath = distInfoDirectoryFullName,
-                    Summary = metadataDict.GetValueOrDefault("summary", [""])[0],
-                    Author = metadataDict.GetValueOrDefault("author", []),
-                    AuthorEmail = metadataDict.GetValueOrDefault("author-email", [""])[0],
+                    Summary = metadata.GetValueOrDefault("summary", [""])[0],
+                    Author = metadata.GetValueOrDefault("author", []),
+                    AuthorEmail = metadata.GetValueOrDefault("author-email", [""])[0],
                     ProjectUrl = projectUrlDictionary,
                     Classifier = classifiers,
-                    Metadata = metadataDict,
+                    Metadata = metadata,
                     Record = record
                 });
             });
@@ -222,7 +230,7 @@ public ActionResponse PurgeEnvironmentCache(EnvironmentItem environmentItem)
         return [.. packages.OrderBy(x => x.Name)];
     }
 
-    public async Task GetVersions(string packageName)
+    public async Task GetVersions(string packageName, CancellationToken cancellationToken, bool detectNonRelease = true)
     {
         try
         {
@@ -231,21 +239,33 @@ public async Task GetVersions(string packageName)
             if (!PackageNameVerificationRegex().IsMatch(packageName))
                 return new GetVersionsResponse { Status = 2, Versions = [] };
             var responseMessage =
-                await _httpClient.GetAsync($"{configurationService.GetUrlFromPackageSourceType("pypi")}{packageName}/json");
-            var response = await responseMessage.Content.ReadAsStringAsync();
+                await _httpClient.GetAsync(
+                    $"{configurationService.GetUrlFromPackageSourceType("pypi")}{packageName}/json", cancellationToken);
+            var response = await responseMessage.Content.ReadAsStringAsync(cancellationToken);
 
             var pypiPackageInfo = JsonConvert.DeserializeObject(response)
                 ?.Releases?
                 .Where(item => item.Value.Count != 0).OrderBy(e => e.Value[0].UploadTime)
                 .ThenBy(e => e.Value[0].UploadTime).ToDictionary(pair => pair.Key, pair => pair.Value);
+
+            if (!detectNonRelease && pypiPackageInfo != null)
+            {
+                pypiPackageInfo = pypiPackageInfo.Where(item => PackageValidator.IsReleaseVersion(item.Key)).ToDictionary();
+            }
+            
             if (pypiPackageInfo == null || pypiPackageInfo.Count == 0)
             {
                 Log.Warning($"[EnvironmentService] {packageName} package not found");
                 return new GetVersionsResponse { Status = 1, Versions = [] };
             }
+
             Log.Information($"[EnvironmentService] Found {packageName}");
             return new GetVersionsResponse { Status = 0, Versions = pypiPackageInfo.Keys.ToArray() };
         }
+        catch (TaskCanceledException)
+        {
+            return new GetVersionsResponse { Status = 1, Versions = [] };
+        }
         catch (Exception)
         {
             Log.Warning($"[EnvironmentService] Unexpected error when get versions of {packageName} package");
@@ -268,6 +288,17 @@ public bool TryKillProcess()
             return false;
         }
     }
+
+    private static string ProcessErrorFilter(string error)
+    {
+        var errorBuilder = new StringBuilder();
+        foreach (var errorLine in error.Split('\n'))
+        {
+            if(!string.IsNullOrWhiteSpace(error) && !errorLine.Contains("[notice]"))
+                errorBuilder.Append(errorLine).Append('\n');
+        }
+        return errorBuilder.ToString().Trim();
+    }
     
     private ActionResponse RaiseProcess(string arguments, DataReceivedEventHandler consoleOutputCallback,
         string[]? extraParameters = null)
@@ -288,11 +319,12 @@ private ActionResponse RaiseProcess(string arguments, DataReceivedEventHandler c
         BasicCommandProcess.OutputDataReceived += consoleOutputCallback;
         BasicCommandProcess.Start();
         BasicCommandProcess.BeginOutputReadLine();
-        var error = BasicCommandProcess.StandardError.ReadToEnd();
+        var error = ProcessErrorFilter(BasicCommandProcess.StandardError.ReadToEnd());
         BasicCommandProcess.WaitForExit();
         BasicCommandProcess.Close();
         BasicCommandProcess.Dispose();
-        return new ActionResponse { Success = string.IsNullOrEmpty(error), Exception = ExceptionType.ProcessError, Message = error };
+        return new ActionResponse { Success = string.IsNullOrEmpty(error), Exception = ExceptionType.ProcessError, Message =
+           error };
     }
 
     #region Basic Command
diff --git a/src/PipManager/Services/Environment/IEnvironmentService.cs b/src/Services/Environment/IEnvironmentService.cs
similarity index 78%
rename from src/PipManager/Services/Environment/IEnvironmentService.cs
rename to src/Services/Environment/IEnvironmentService.cs
index a9e7bb9..022107e 100644
--- a/src/PipManager/Services/Environment/IEnvironmentService.cs
+++ b/src/Services/Environment/IEnvironmentService.cs
@@ -1,9 +1,9 @@
-using PipManager.Models.AppConfigModels;
-using PipManager.Models.Package;
-using PipManager.Services.Environment.Response;
-using System.Diagnostics;
+using System.Diagnostics;
+using PipManager.Windows.Models.AppConfigModels;
+using PipManager.Windows.Models.Package;
+using PipManager.Windows.Services.Environment.Response;
 
-namespace PipManager.Services.Environment;
+namespace PipManager.Windows.Services.Environment;
 
 public interface IEnvironmentService
 {
@@ -15,7 +15,7 @@ public interface IEnvironmentService
 
     public Task?> GetLibraries();
 
-    public Task GetVersions(string packageName);
+    public Task GetVersions(string packageName, CancellationToken cancellationToken, bool detectNonRelease = true);
     public bool TryKillProcess();
 
     public ActionResponse Install(string packageName, DataReceivedEventHandler consoleOutputCallback, string[]? extraParameters = null);
diff --git a/src/PipManager/Services/Environment/Response/ActionResponse.cs b/src/Services/Environment/Response/ActionResponse.cs
similarity index 64%
rename from src/PipManager/Services/Environment/Response/ActionResponse.cs
rename to src/Services/Environment/Response/ActionResponse.cs
index a7a3a03..51c3f80 100644
--- a/src/PipManager/Services/Environment/Response/ActionResponse.cs
+++ b/src/Services/Environment/Response/ActionResponse.cs
@@ -1,6 +1,6 @@
-using PipManager.Models;
+using PipManager.Windows.Models;
 
-namespace PipManager.Services.Environment.Response;
+namespace PipManager.Windows.Services.Environment.Response;
 
 public class ActionResponse
 {
diff --git a/src/PipManager/Services/Environment/Response/GetVersionsResponse.cs b/src/Services/Environment/Response/GetVersionsResponse.cs
similarity index 72%
rename from src/PipManager/Services/Environment/Response/GetVersionsResponse.cs
rename to src/Services/Environment/Response/GetVersionsResponse.cs
index b5b1e92..a597e10 100644
--- a/src/PipManager/Services/Environment/Response/GetVersionsResponse.cs
+++ b/src/Services/Environment/Response/GetVersionsResponse.cs
@@ -1,4 +1,4 @@
-namespace PipManager.Services.Environment.Response;
+namespace PipManager.Windows.Services.Environment.Response;
 
 public class GetVersionsResponse
 {
diff --git a/src/Services/Environment/Response/ParseRequirementsResponse.cs b/src/Services/Environment/Response/ParseRequirementsResponse.cs
new file mode 100644
index 0000000..3587f4f
--- /dev/null
+++ b/src/Services/Environment/Response/ParseRequirementsResponse.cs
@@ -0,0 +1,13 @@
+namespace PipManager.Windows.Services.Environment.Response;
+
+public class ParseRequirementsResponse
+{
+    public bool Success { get; init; }
+    public List? Requirements { get; init; }
+}
+
+public class ParsedRequirement
+{
+    public required string Name { get; init; }
+    public required string Specifier { get; init; }
+}
diff --git a/src/PipManager/Services/Mask/IMaskService.cs b/src/Services/Mask/IMaskService.cs
similarity index 65%
rename from src/PipManager/Services/Mask/IMaskService.cs
rename to src/Services/Mask/IMaskService.cs
index e452d74..e16e7a6 100644
--- a/src/PipManager/Services/Mask/IMaskService.cs
+++ b/src/Services/Mask/IMaskService.cs
@@ -1,6 +1,6 @@
-using PipManager.Controls.Mask;
+using PipManager.Windows.Controls.Mask;
 
-namespace PipManager.Services.Mask;
+namespace PipManager.Windows.Services.Mask;
 
 public interface IMaskService
 {
diff --git a/src/PipManager/Services/Mask/MaskService.cs b/src/Services/Mask/MaskService.cs
similarity index 85%
rename from src/PipManager/Services/Mask/MaskService.cs
rename to src/Services/Mask/MaskService.cs
index b44e18c..d919fdf 100644
--- a/src/PipManager/Services/Mask/MaskService.cs
+++ b/src/Services/Mask/MaskService.cs
@@ -1,8 +1,8 @@
-using PipManager.Controls.Mask;
-using PipManager.Languages;
-using System.Windows.Controls;
+using System.Windows.Controls;
+using PipManager.Windows.Controls.Mask;
+using PipManager.Windows.Languages;
 
-namespace PipManager.Services.Mask;
+namespace PipManager.Windows.Services.Mask;
 
 public class MaskService : IMaskService
 {
diff --git a/src/Services/Overlay/IOverlayService.cs b/src/Services/Overlay/IOverlayService.cs
new file mode 100644
index 0000000..47c3dbc
--- /dev/null
+++ b/src/Services/Overlay/IOverlayService.cs
@@ -0,0 +1,9 @@
+using PipManager.Windows.Models.Package;
+
+namespace PipManager.Windows.Services.Overlay;
+
+public interface IOverlayService
+{
+    public void ShowPackageUpdateOverlay(List packageUpdates, System.Action callback);
+
+}
diff --git a/src/Services/Overlay/OverlayService.cs b/src/Services/Overlay/OverlayService.cs
new file mode 100644
index 0000000..02a3d71
--- /dev/null
+++ b/src/Services/Overlay/OverlayService.cs
@@ -0,0 +1,22 @@
+using System.Collections.ObjectModel;
+using PipManager.Windows.Models.Package;
+using PipManager.Windows.ViewModels.Pages.Overlay;
+using PipManager.Windows.ViewModels.Windows;
+
+namespace PipManager.Windows.Services.Overlay;
+
+public class OverlayService(OverlayViewModel overlayViewModel, MainWindowViewModel mainWindowViewModel): IOverlayService
+{
+    private void ShowOverlay()
+    {
+        overlayViewModel.IsOverlayVisible = true;
+        mainWindowViewModel.IsTitleBarCoverageGridVisible = true;
+    }
+    
+    public void ShowPackageUpdateOverlay(List packageUpdates, System.Action callback)
+    {
+        overlayViewModel.ConfirmCallback = callback;
+        overlayViewModel.PackageUpdateItems = new ObservableCollection(packageUpdates);
+        ShowOverlay();
+    }
+}
diff --git a/src/PipManager/Services/Toast/IToastService.cs b/src/Services/Toast/IToastService.cs
similarity index 80%
rename from src/PipManager/Services/Toast/IToastService.cs
rename to src/Services/Toast/IToastService.cs
index 02b0ac5..7ca8fbe 100644
--- a/src/PipManager/Services/Toast/IToastService.cs
+++ b/src/Services/Toast/IToastService.cs
@@ -1,4 +1,4 @@
-namespace PipManager.Services.Toast;
+namespace PipManager.Windows.Services.Toast;
 
 public interface IToastService
 {
diff --git a/src/PipManager/Services/Toast/ToastService.cs b/src/Services/Toast/ToastService.cs
similarity index 89%
rename from src/PipManager/Services/Toast/ToastService.cs
rename to src/Services/Toast/ToastService.cs
index a409922..6eea1bb 100644
--- a/src/PipManager/Services/Toast/ToastService.cs
+++ b/src/Services/Toast/ToastService.cs
@@ -1,8 +1,8 @@
-using PipManager.Controls;
-using PipManager.Languages;
+using PipManager.Windows.Controls;
+using PipManager.Windows.Languages;
 using Wpf.Ui;
 
-namespace PipManager.Services.Toast;
+namespace PipManager.Windows.Services.Toast;
 
 public class ToastService(IThemeService themeService) : IToastService
 {
diff --git a/src/PipManager/ViewModels/Pages/About/AboutViewModel.cs b/src/ViewModels/Pages/About/AboutViewModel.cs
similarity index 88%
rename from src/PipManager/ViewModels/Pages/About/AboutViewModel.cs
rename to src/ViewModels/Pages/About/AboutViewModel.cs
index c63e46d..6b693a8 100644
--- a/src/PipManager/ViewModels/Pages/About/AboutViewModel.cs
+++ b/src/ViewModels/Pages/About/AboutViewModel.cs
@@ -1,10 +1,10 @@
-using PipManager.Models.Pages;
-using PipManager.Services.Configuration;
-using Serilog;
+using Serilog;
 using System.Collections.ObjectModel;
+using PipManager.Windows.Models.Pages;
+using PipManager.Windows.Services.Configuration;
 using Wpf.Ui.Controls;
 
-namespace PipManager.ViewModels.Pages.About;
+namespace PipManager.Windows.ViewModels.Pages.About;
 
 public partial class AboutViewModel(IConfigurationService configurationService) : ObservableObject, INavigationAware
 {
@@ -48,6 +48,8 @@ private void InitializeViewModel()
                 "https://github.com/microsoft/XamlBehaviorsWpf"),
             new AboutNugetLibraryListItem("Newtonsoft.Json", "MIT", "Copyright (c) 2007 James Newton-King",
                 "https://github.com/JamesNK/Newtonsoft.Json"),
+            new AboutNugetLibraryListItem("pythonnet", "MIT", "Copyright (c) 2006-2021 the contributors of the Python.NET project",
+                "https://github.com/pythonnet/pythonnet"),
             new AboutNugetLibraryListItem("Serilog", "Apache-2.0", "Copyright © 2013-2020 Serilog Contributors",
                 "https://github.com/serilog/serilog"),
             new AboutNugetLibraryListItem("Serilog.Extensions.Logging", "Apache-2.0",
@@ -66,6 +68,9 @@ private void InitializeViewModel()
             new AboutNugetLibraryListItem("WPF-UI.Tray", "MIT",
                 "Copyright (c) 2021-2023 Leszek Pomianowski and WPF UI Contributors",
                 "https://github.com/lepoco/wpfui"),
+            new AboutNugetLibraryListItem("XamlFlair.WPF", "MIT",
+                "Copyright (c) 2019 XamlFlair",
+                "https://github.com/XamlFlair/XamlFlair")
         ];
         Log.Information("[About] Initialized");
     }
diff --git a/src/PipManager/ViewModels/Pages/Action/ActionExceptionViewModel.cs b/src/ViewModels/Pages/Action/ActionExceptionViewModel.cs
similarity index 92%
rename from src/PipManager/ViewModels/Pages/Action/ActionExceptionViewModel.cs
rename to src/ViewModels/Pages/Action/ActionExceptionViewModel.cs
index d8466d7..3dc8bac 100644
--- a/src/PipManager/ViewModels/Pages/Action/ActionExceptionViewModel.cs
+++ b/src/ViewModels/Pages/Action/ActionExceptionViewModel.cs
@@ -1,16 +1,16 @@
-using PipManager.Languages;
-using PipManager.Models.Action;
-using PipManager.Services.Action;
-using PipManager.Services.Toast;
-using Serilog;
+using Serilog;
 using System.Collections.ObjectModel;
 using System.Diagnostics;
 using System.IO;
 using System.Text;
 using System.Web;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models.Action;
+using PipManager.Windows.Services.Action;
+using PipManager.Windows.Services.Toast;
 using Wpf.Ui.Controls;
 
-namespace PipManager.ViewModels.Pages.Action;
+namespace PipManager.Windows.ViewModels.Pages.Action;
 
 public partial class ActionExceptionViewModel : ObservableObject, INavigationAware
 {
diff --git a/src/PipManager/ViewModels/Pages/Action/ActionViewModel.cs b/src/ViewModels/Pages/Action/ActionViewModel.cs
similarity index 87%
rename from src/PipManager/ViewModels/Pages/Action/ActionViewModel.cs
rename to src/ViewModels/Pages/Action/ActionViewModel.cs
index 929f05b..e415041 100644
--- a/src/PipManager/ViewModels/Pages/Action/ActionViewModel.cs
+++ b/src/ViewModels/Pages/Action/ActionViewModel.cs
@@ -1,14 +1,14 @@
 using Meziantou.Framework.WPF.Collections;
-using PipManager.Languages;
-using PipManager.Models.Action;
-using PipManager.Services.Action;
-using PipManager.Services.Toast;
-using PipManager.Views.Pages.Action;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models.Action;
+using PipManager.Windows.Services.Action;
+using PipManager.Windows.Services.Toast;
+using PipManager.Windows.Views.Pages.Action;
 using Serilog;
 using Wpf.Ui;
 using Wpf.Ui.Controls;
 
-namespace PipManager.ViewModels.Pages.Action;
+namespace PipManager.Windows.ViewModels.Pages.Action;
 
 public partial class ActionViewModel : ObservableObject, INavigationAware
 {
diff --git a/src/PipManager/ViewModels/Pages/Environment/AddEnvironmentViewModel.cs b/src/ViewModels/Pages/Environment/AddEnvironmentViewModel.cs
similarity index 96%
rename from src/PipManager/ViewModels/Pages/Environment/AddEnvironmentViewModel.cs
rename to src/ViewModels/Pages/Environment/AddEnvironmentViewModel.cs
index 0aa1738..aab27e3 100644
--- a/src/PipManager/ViewModels/Pages/Environment/AddEnvironmentViewModel.cs
+++ b/src/ViewModels/Pages/Environment/AddEnvironmentViewModel.cs
@@ -1,15 +1,15 @@
 using Microsoft.Win32;
-using PipManager.Languages;
-using PipManager.Models.AppConfigModels;
-using PipManager.Services.Configuration;
-using PipManager.Services.Environment;
-using PipManager.Services.Toast;
 using Serilog;
 using System.IO;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models.AppConfigModels;
+using PipManager.Windows.Services.Configuration;
+using PipManager.Windows.Services.Environment;
+using PipManager.Windows.Services.Toast;
 using Wpf.Ui;
 using Wpf.Ui.Controls;
 
-namespace PipManager.ViewModels.Pages.Environment;
+namespace PipManager.Windows.ViewModels.Pages.Environment;
 
 public partial class AddEnvironmentViewModel(INavigationService navigationService, IConfigurationService configurationService, IEnvironmentService environmentService, IToastService toastService) : ObservableObject, INavigationAware
 {
diff --git a/src/PipManager/ViewModels/Pages/Environment/EnvironmentViewModel.cs b/src/ViewModels/Pages/Environment/EnvironmentViewModel.cs
similarity index 87%
rename from src/PipManager/ViewModels/Pages/Environment/EnvironmentViewModel.cs
rename to src/ViewModels/Pages/Environment/EnvironmentViewModel.cs
index 40e1176..6046a4c 100644
--- a/src/PipManager/ViewModels/Pages/Environment/EnvironmentViewModel.cs
+++ b/src/ViewModels/Pages/Environment/EnvironmentViewModel.cs
@@ -1,23 +1,23 @@
-using PipManager.Controls;
-using PipManager.Languages;
-using PipManager.Models.Action;
-using PipManager.Models.AppConfigModels;
-using PipManager.Services.Action;
-using PipManager.Services.Configuration;
-using PipManager.Services.Environment;
-using PipManager.Services.Mask;
-using PipManager.Services.Toast;
-using PipManager.ViewModels.Windows;
-using PipManager.Views.Pages.Action;
-using PipManager.Views.Pages.Environment;
-using Serilog;
+using Serilog;
 using System.Collections.ObjectModel;
 using System.ComponentModel;
+using PipManager.Windows.Controls;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models.Action;
+using PipManager.Windows.Models.AppConfigModels;
+using PipManager.Windows.Services.Action;
+using PipManager.Windows.Services.Configuration;
+using PipManager.Windows.Services.Environment;
+using PipManager.Windows.Services.Mask;
+using PipManager.Windows.Services.Toast;
+using PipManager.Windows.ViewModels.Windows;
+using PipManager.Windows.Views.Pages.Action;
+using PipManager.Windows.Views.Pages.Environment;
 using Wpf.Ui;
 using Wpf.Ui.Controls;
 using Wpf.Ui.Extensions;
 
-namespace PipManager.ViewModels.Pages.Environment;
+namespace PipManager.Windows.ViewModels.Pages.Environment;
 
 public partial class EnvironmentViewModel(INavigationService navigationService,
         IConfigurationService configurationService, IEnvironmentService environmentService,
@@ -31,8 +31,10 @@ public void OnNavigatedTo()
     {
         if (!_isInitialized)
             InitializeViewModel();
+        
         configurationService.RefreshAllEnvironmentVersions();
-        EnvironmentItems = new ObservableCollection(configurationService.AppConfig.EnvironmentItems);
+        EnvironmentItems =
+            new ObservableCollection(configurationService.AppConfig.EnvironmentItems);
         var currentEnvironment = configurationService.AppConfig.CurrentEnvironment;
         foreach (var environmentItem in EnvironmentItems)
         {
@@ -42,9 +44,12 @@ public void OnNavigatedTo()
             }
 
             CurrentEnvironment = environmentItem;
+        
             var mainWindowViewModel = App.GetService();
-            mainWindowViewModel.ApplicationTitle = $"Pip Manager | {CurrentEnvironment.PipVersion} for {CurrentEnvironment.PythonVersion}";
+            mainWindowViewModel.ApplicationTitle =
+                $"Pip Manager | {CurrentEnvironment.PipVersion} for {CurrentEnvironment.PythonVersion}";
             Log.Information($"[Environment] Current Environment changed: {CurrentEnvironment.PythonPath}");
+            break;
         }
     }
 
@@ -112,7 +117,7 @@ private async Task CheckEnvironmentUpdate()
         var latest = "";
         await Task.Run(async () =>
         {
-            var versions = await environmentService.GetVersions("pip");
+            var versions = await environmentService.GetVersions("pip", new CancellationToken(), configurationService.AppConfig.PackageSource.DetectNonReleaseVersion);
             if (versions.Status == 0)
             {
                 latest = versions.Versions!.Last();
@@ -176,7 +181,6 @@ protected override void OnPropertyChanged(PropertyChangedEventArgs e)
             mainWindowViewModel.ApplicationTitle = $"Pip Manager | {CurrentEnvironment.PipVersion} for {CurrentEnvironment.PythonVersion}";
             configurationService.AppConfig.CurrentEnvironment = CurrentEnvironment;
             configurationService.Save();
-            EnvironmentSelected = true;
             Log.Information($"[Environment] Environment changed ({CurrentEnvironment.PipVersion} for {CurrentEnvironment.PythonVersion})");
         }
     }
diff --git a/src/PipManager/ViewModels/Pages/Lab/LabViewModel.cs b/src/ViewModels/Pages/Lab/LabViewModel.cs
similarity index 83%
rename from src/PipManager/ViewModels/Pages/Lab/LabViewModel.cs
rename to src/ViewModels/Pages/Lab/LabViewModel.cs
index c34112b..5c0797e 100644
--- a/src/PipManager/ViewModels/Pages/Lab/LabViewModel.cs
+++ b/src/ViewModels/Pages/Lab/LabViewModel.cs
@@ -1,9 +1,9 @@
-using PipManager.Models.Action;
-using PipManager.Services.Action;
+using PipManager.Windows.Models.Action;
+using PipManager.Windows.Services.Action;
 using Serilog;
 using Wpf.Ui.Controls;
 
-namespace PipManager.ViewModels.Pages.Lab;
+namespace PipManager.Windows.ViewModels.Pages.Lab;
 
 public partial class LabViewModel(IActionService actionService)
     : ObservableObject, INavigationAware
diff --git a/src/PipManager/ViewModels/Pages/Library/LibraryDetailViewModel.cs b/src/ViewModels/Pages/Library/LibraryDetailViewModel.cs
similarity index 79%
rename from src/PipManager/ViewModels/Pages/Library/LibraryDetailViewModel.cs
rename to src/ViewModels/Pages/Library/LibraryDetailViewModel.cs
index 95af72f..c979fc5 100644
--- a/src/PipManager/ViewModels/Pages/Library/LibraryDetailViewModel.cs
+++ b/src/ViewModels/Pages/Library/LibraryDetailViewModel.cs
@@ -1,19 +1,24 @@
 using CommunityToolkit.Mvvm.Messaging;
-using PipManager.Languages;
-using PipManager.Models.Package;
-using PipManager.Models.Pages;
 using System.Collections.ObjectModel;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models.Package;
+using PipManager.Windows.Models.Pages;
+using PipManager.Windows.Services.Toast;
+using PipManager.Windows.Views.Pages.Library;
+using Wpf.Ui;
 using Wpf.Ui.Controls;
 
-namespace PipManager.ViewModels.Pages.Library;
+namespace PipManager.Windows.ViewModels.Pages.Library;
 
 public partial class LibraryDetailViewModel : ObservableObject, INavigationAware
 {
-    public record LibraryDetailMessage(PackageItem Package);
+    private readonly INavigationService _navigationService;
+    private readonly IToastService _toastService;
+    public record LibraryDetailMessage(PackageItem Package, List Library);
     private bool _isInitialized;
 
-    [ObservableProperty]
-    private PackageItem? _package;
+    [ObservableProperty] private PackageItem? _package;
+    [ObservableProperty] private List? _library;
 
     #region Contact
 
@@ -36,8 +41,10 @@ public record LibraryDetailMessage(PackageItem Package);
 
     #endregion Classifier
 
-    public LibraryDetailViewModel()
+    public LibraryDetailViewModel(INavigationService navigationService, IToastService toastService)
     {
+        _navigationService = navigationService;
+        _toastService = toastService;
         WeakReferenceMessenger.Default.Register(this, Receive);
     }
 
@@ -55,11 +62,25 @@ private void InitializeViewModel()
     {
         _isInitialized = true;
     }
+    
+    [RelayCommand]
+    private void NavigateToDependency(string name)
+    {
+        var targetPackage = Library!.FirstOrDefault(item => item!.Name!.Equals(name, StringComparison.CurrentCultureIgnoreCase), null);
+        if (targetPackage is null)
+        {
+            _toastService.Error(Lang.LibraryDetail_Toast_PackageNotFound);
+            return;
+        }
+        _navigationService.NavigateWithHierarchy(typeof(LibraryDetailPage));
+        WeakReferenceMessenger.Default.Send(new LibraryDetailMessage(targetPackage, Library!));
+    }
 
     private void Receive(object recipient, LibraryDetailMessage message)
     {
         Package = message.Package;
-
+        Library = message.Library;
+        
         #region Contact
 
         Author = Package.Author!.Count == 0 ? Lang.LibraryDetail_Unknown : string.Join(", ", Package.Author!);
@@ -67,7 +88,7 @@ private void Receive(object recipient, LibraryDetailMessage message)
         ProjectUrl = new ObservableCollection(Package.ProjectUrl!);
 
         #endregion Contact
-
+        
         #region Classifier
 
         // Development Status
diff --git a/src/PipManager/ViewModels/Pages/Library/LibraryInstallViewModel.cs b/src/ViewModels/Pages/Library/LibraryInstallViewModel.cs
similarity index 93%
rename from src/PipManager/ViewModels/Pages/Library/LibraryInstallViewModel.cs
rename to src/ViewModels/Pages/Library/LibraryInstallViewModel.cs
index ad1d0da..ddfd5d6 100644
--- a/src/PipManager/ViewModels/Pages/Library/LibraryInstallViewModel.cs
+++ b/src/ViewModels/Pages/Library/LibraryInstallViewModel.cs
@@ -1,24 +1,25 @@
 using CommunityToolkit.Mvvm.Messaging;
 using Microsoft.Win32;
-using PipManager.Resources.Library;
-using PipManager.Languages;
-using PipManager.Models.Action;
-using PipManager.Models.Pages;
-using PipManager.Services.Action;
-using PipManager.Services.Environment;
-using PipManager.Services.Mask;
-using PipManager.Services.Toast;
-using PipManager.Views.Pages.Action;
 using System.Collections.ObjectModel;
 using System.IO;
 using System.IO.Compression;
 using System.Text;
 using ICSharpCode.SharpZipLib.GZip;
 using ICSharpCode.SharpZipLib.Tar;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models.Action;
+using PipManager.Windows.Models.Pages;
+using PipManager.Windows.Resources.Library;
+using PipManager.Windows.Services.Action;
+using PipManager.Windows.Services.Configuration;
+using PipManager.Windows.Services.Environment;
+using PipManager.Windows.Services.Mask;
+using PipManager.Windows.Services.Toast;
+using PipManager.Windows.Views.Pages.Action;
 using Wpf.Ui;
 using Wpf.Ui.Controls;
 
-namespace PipManager.ViewModels.Pages.Library;
+namespace PipManager.Windows.ViewModels.Pages.Library;
 
 public partial class LibraryInstallViewModel : ObservableObject, INavigationAware
 {
@@ -32,8 +33,9 @@ public record InstalledPackagesMessage(List InstalledPackages);
     private readonly IEnvironmentService _environmentService;
     private readonly IToastService _toastService;
     private readonly INavigationService _navigationService;
+    private readonly IConfigurationService _configurationService;
 
-    public LibraryInstallViewModel(IActionService actionService, IMaskService maskService, IContentDialogService contentDialogService, IEnvironmentService environmentService, IToastService toastService, INavigationService navigationService)
+    public LibraryInstallViewModel(IActionService actionService, IMaskService maskService, IContentDialogService contentDialogService, IEnvironmentService environmentService, IToastService toastService, INavigationService navigationService, IConfigurationService configurationService)
     {
         _actionService = actionService;
         _maskService = maskService;
@@ -42,6 +44,7 @@ public LibraryInstallViewModel(IActionService actionService, IMaskService maskSe
         _toastService = toastService;
         _installWheelDependencies = false;
         _navigationService = navigationService;
+        _configurationService = configurationService;
         WeakReferenceMessenger.Default.Register(this, Receive);
     }
 
@@ -55,6 +58,7 @@ public void OnNavigatedTo()
     public void OnNavigatedFrom()
     {
         PreInstallPackages.Clear();
+        PreDownloadPackages.Clear();
     }
 
     private void InitializeViewModel()
@@ -92,7 +96,8 @@ private async Task AddDefaultTask()
             return;
         }
         _maskService.Show(Lang.LibraryInstall_Add_Verifying);
-        var packageVersions = await _environmentService.GetVersions(packageName);
+        var detectNonRelease = _configurationService.AppConfig.PackageSource.DetectNonReleaseVersion;
+        var packageVersions = await _environmentService.GetVersions(packageName, new CancellationToken(), detectNonRelease);
         _maskService.Hide();
         switch (packageVersions.Status)
         {
@@ -208,7 +213,7 @@ private async Task DownloadDistributionsTask()
             return;
         }
         _maskService.Show(Lang.LibraryInstall_Add_Verifying);
-        var packageVersions = await _environmentService.GetVersions(packageName);
+        var packageVersions = await _environmentService.GetVersions(packageName, new CancellationToken(), _configurationService.AppConfig.PackageSource.DetectNonReleaseVersion);
         _maskService.Hide();
         switch (packageVersions.Status)
         {
diff --git a/src/PipManager/ViewModels/Pages/Library/LibraryViewModel.cs b/src/ViewModels/Pages/Library/LibraryViewModel.cs
similarity index 76%
rename from src/PipManager/ViewModels/Pages/Library/LibraryViewModel.cs
rename to src/ViewModels/Pages/Library/LibraryViewModel.cs
index 4bb123d..216d6cd 100644
--- a/src/PipManager/ViewModels/Pages/Library/LibraryViewModel.cs
+++ b/src/ViewModels/Pages/Library/LibraryViewModel.cs
@@ -1,27 +1,28 @@
 using CommunityToolkit.Mvvm.Messaging;
-using PipManager.Resources.Library;
-using PipManager.Languages;
-using PipManager.Models.Action;
-using PipManager.Models.Package;
-using PipManager.Models.Pages;
-using PipManager.Services.Action;
-using PipManager.Services.Configuration;
-using PipManager.Services.Environment;
-using PipManager.Services.Mask;
-using PipManager.Services.Toast;
-using PipManager.Views.Pages.Action;
-using PipManager.Views.Pages.Environment;
-using PipManager.Views.Pages.Library;
 using Serilog;
 using System.Collections.ObjectModel;
-using PipManager.ViewModels.Pages.Overlay;
+using System.Diagnostics;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models.Action;
+using PipManager.Windows.Models.Package;
+using PipManager.Windows.Models.Pages;
+using PipManager.Windows.Resources.Library;
+using PipManager.Windows.Services.Action;
+using PipManager.Windows.Services.Configuration;
+using PipManager.Windows.Services.Environment;
+using PipManager.Windows.Services.Mask;
+using PipManager.Windows.Services.Overlay;
+using PipManager.Windows.Services.Toast;
+using PipManager.Windows.Views.Pages.Action;
+using PipManager.Windows.Views.Pages.Environment;
+using PipManager.Windows.Views.Pages.Library;
 using Wpf.Ui;
 using Wpf.Ui.Appearance;
 using Wpf.Ui.Controls;
-using static PipManager.ViewModels.Pages.Library.LibraryDetailViewModel;
-using static PipManager.ViewModels.Pages.Library.LibraryInstallViewModel;
+using static PipManager.Windows.ViewModels.Pages.Library.LibraryDetailViewModel;
+using static PipManager.Windows.ViewModels.Pages.Library.LibraryInstallViewModel;
 
-namespace PipManager.ViewModels.Pages.Library;
+namespace PipManager.Windows.ViewModels.Pages.Library;
 
 public partial class LibraryViewModel : ObservableObject, INavigationAware
 {
@@ -34,9 +35,9 @@ public partial class LibraryViewModel : ObservableObject, INavigationAware
     private readonly IMaskService _maskService;
     private readonly IToastService _toastService;
     private readonly IContentDialogService _contentDialogService;
-    private readonly OverlayViewModel _overlayViewModel;
+    private readonly IOverlayService _overlayService;
 
-    public LibraryViewModel(INavigationService navigationService, IEnvironmentService environmentService, OverlayViewModel overlayViewModel,
+    public LibraryViewModel(INavigationService navigationService, IEnvironmentService environmentService, IOverlayService overlayService,
         IConfigurationService configurationService, IActionService actionService, IThemeService themeService, IMaskService maskService, IToastService toastService, IContentDialogService contentDialogService)
     {
         _navigationService = navigationService;
@@ -46,7 +47,7 @@ public LibraryViewModel(INavigationService navigationService, IEnvironmentServic
         _maskService = maskService;
         _toastService = toastService;
         _contentDialogService = contentDialogService;
-        _overlayViewModel = overlayViewModel;
+        _overlayService = overlayService;
 
         themeService.SetTheme(_configurationService.AppConfig.Personalization.Theme switch
         {
@@ -79,7 +80,7 @@ private void InitializeViewModel()
     private void InstallPackage()
     {
         _navigationService.NavigateWithHierarchy(typeof(LibraryInstallPage));
-        WeakReferenceMessenger.Default.Send(new InstalledPackagesMessage([.. LibraryList]));
+        WeakReferenceMessenger.Default.Send(new LibraryInstallViewModel.InstalledPackagesMessage([.. LibraryList]));
     }
 
     #endregion Install Package
@@ -115,12 +116,13 @@ private async Task CheckUpdate()
         var operationList = "";
         var ioTaskList = new List();
         var msgListLock = new object();
+        var detectNonRelease = _configurationService.AppConfig.PackageSource.DetectNonReleaseVersion;
         await Task.Run(() =>
         {
             var selected = LibraryList.Where(libraryListItem => libraryListItem.IsSelected).ToList();
-            ioTaskList.AddRange(selected.Select(item => Task.Run(() =>
+            ioTaskList.AddRange(selected.Select(item => Task.Run(async () =>
             {
-                var latest = _environmentService.GetVersions(item.PackageName.ToLower().Replace('_', '-')).Result;
+                var latest = await _environmentService.GetVersions(item.PackageName.ToLower().Replace('_', '-'), new CancellationToken(), detectNonRelease);
                 if (latest.Status != 0 || item.PackageVersion == latest.Versions!.Last()) return;
                 lock (msgListLock)
                 {
@@ -137,7 +139,7 @@ await Task.Run(() =>
         }
         else
         {
-            _overlayViewModel.ShowPackageUpdateOverlay(msgList, () =>
+            _overlayService.ShowPackageUpdateOverlay(msgList, () =>
             {
                 _actionService.AddOperation(new ActionListItem
                 (
@@ -160,7 +162,7 @@ private void ToDetailPage(object parameter)
         if (_library is null) return;
         _navigationService.NavigateWithHierarchy(typeof(LibraryDetailPage));
         var current = _library.Where(libraryListItem => libraryListItem.Name == parameter as string).ToList()[0];
-        WeakReferenceMessenger.Default.Send(new LibraryDetailMessage(current));
+        WeakReferenceMessenger.Default.Send(new LibraryDetailViewModel.LibraryDetailMessage(current, _library));
         Log.Information($"[Library] Turn to detail page: {current.Name}");
     }
 
@@ -178,9 +180,15 @@ private void NavigateToAddEnvironment()
         _navigationService.Navigate(typeof(AddEnvironmentPage));
     }
 
+    [ObservableProperty] private double _refreshTimeUsage;
+    
+    private readonly Stopwatch _refreshStopwatch = new();
+
     [RelayCommand]
     private async Task RefreshLibrary()
     {
+        _refreshStopwatch.Reset();
+        _refreshStopwatch.Start();
         LibraryList = [];
         EnvironmentFoundVisible = true;
         _maskService.Show(Lang.MainWindow_NavigationContent_Library);
@@ -208,7 +216,11 @@ await Task.Run(async () =>
                 ));
             }
             LibraryListLength = _library.Count;
+            _refreshStopwatch.Stop();
+            RefreshTimeUsage = Math.Round(_refreshStopwatch.Elapsed.TotalMilliseconds / 1000.0, 3);
             Log.Information("[Library] Package list refreshed successfully");
+            return;
         }
+        RefreshTimeUsage = 0;
     }
 }
\ No newline at end of file
diff --git a/src/ViewModels/Pages/Overlay/OverlayViewModel.cs b/src/ViewModels/Pages/Overlay/OverlayViewModel.cs
new file mode 100644
index 0000000..bb7ca41
--- /dev/null
+++ b/src/ViewModels/Pages/Overlay/OverlayViewModel.cs
@@ -0,0 +1,29 @@
+using System.Collections.ObjectModel;
+using PipManager.Windows.Models.Package;
+using PipManager.Windows.ViewModels.Windows;
+
+namespace PipManager.Windows.ViewModels.Pages.Overlay;
+
+public partial class OverlayViewModel(MainWindowViewModel mainWindowViewModel): ObservableObject
+{
+    public System.Action? ConfirmCallback { get; set; }
+    
+    [ObservableProperty]
+    private bool _isOverlayVisible;
+    
+    [RelayCommand]
+    private void CloseOverlay()
+    {
+        IsOverlayVisible = false;
+        mainWindowViewModel.IsTitleBarCoverageGridVisible = false;
+    }
+
+    [ObservableProperty] private ObservableCollection _packageUpdateItems = [];
+
+    [RelayCommand]
+    private void Confirm()
+    {
+        CloseOverlay();
+        ConfirmCallback?.Invoke();
+    }
+}
diff --git a/src/PipManager/ViewModels/Pages/Search/SearchDetailViewModel.cs b/src/ViewModels/Pages/Search/SearchDetailViewModel.cs
similarity index 88%
rename from src/PipManager/ViewModels/Pages/Search/SearchDetailViewModel.cs
rename to src/ViewModels/Pages/Search/SearchDetailViewModel.cs
index b5c71e0..1b3fc08 100644
--- a/src/PipManager/ViewModels/Pages/Search/SearchDetailViewModel.cs
+++ b/src/ViewModels/Pages/Search/SearchDetailViewModel.cs
@@ -1,23 +1,24 @@
 using CommunityToolkit.Mvvm.Messaging;
 using HtmlAgilityPack;
 using Microsoft.Web.WebView2.Core;
-using PipManager.Languages;
-using PipManager.PackageSearch.Wrappers.Query;
-using PipManager.Services.Environment;
-using PipManager.Services.Toast;
-using PipManager.Views.Pages.Search;
 using Serilog;
 using System.Collections.ObjectModel;
 using System.Drawing;
 using System.Net.Http;
 using Microsoft.Win32;
-using PipManager.Models.Action;
-using PipManager.Services.Action;
+using PipManager.Core.Wrappers.PackageSearchQueryWrapper;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models.Action;
+using PipManager.Windows.Services.Action;
+using PipManager.Windows.Services.Configuration;
+using PipManager.Windows.Services.Environment;
+using PipManager.Windows.Services.Toast;
+using PipManager.Windows.Views.Pages.Search;
 using Wpf.Ui;
 using Wpf.Ui.Appearance;
 using Wpf.Ui.Controls;
 
-namespace PipManager.ViewModels.Pages.Search;
+namespace PipManager.Windows.ViewModels.Pages.Search;
 
 public partial class SearchDetailViewModel : ObservableObject, INavigationAware
 {
@@ -29,6 +30,7 @@ public record SearchDetailMessage(QueryListItemModel Package);
     private readonly IToastService _toastService;
     private readonly IActionService _actionService;
     private readonly IEnvironmentService _environmentService;
+    private readonly IConfigurationService _configurationService;
 
     [ObservableProperty]
     private bool _projectDescriptionVisibility;
@@ -59,7 +61,7 @@ public record SearchDetailMessage(QueryListItemModel Package);
     [ObservableProperty]
     private QueryListItemModel? _package;
 
-    public SearchDetailViewModel(INavigationService navigationService, HttpClient httpClient, IThemeService themeService, IToastService toastService, IEnvironmentService environmentService, IActionService actionService)
+    public SearchDetailViewModel(INavigationService navigationService, HttpClient httpClient, IThemeService themeService, IToastService toastService, IEnvironmentService environmentService, IActionService actionService, IConfigurationService configurationService)
     {
         _navigationService = navigationService;
         _httpClient = httpClient;
@@ -67,6 +69,7 @@ public SearchDetailViewModel(INavigationService navigationService, HttpClient ht
         _toastService = toastService;
         _environmentService = environmentService;
         _actionService = actionService;
+        _configurationService = configurationService;
 
         WeakReferenceMessenger.Default.Register(this, Receive);
     }
@@ -162,16 +165,14 @@ private void Receive(object recipient, SearchDetailMessage message)
         SearchDetailPage.ProjectDescriptionWebView!.Loaded += async (_, _) =>
         {
             ProjectDescriptionVisibility = false;
-            var packageVersions = await _environmentService.GetVersions(Package!.Name);
+            var packageVersions = await _environmentService.GetVersions(Package!.Name, new CancellationToken(), _configurationService.AppConfig.PackageSource.DetectNonReleaseVersion);
             switch (packageVersions.Status)
             {
-                case 1:
-                    _toastService.Error(Lang.LibraryInstall_Add_PackageNotFound);
-                    break;
-
-                case 2:
-                    _toastService.Error(Lang.LibraryInstall_Add_InvalidPackageName);
-                    break;
+                case 1 or 2:
+                    _toastService.Error(Lang.SearchDetail_Exception_NetworkError);
+                    await Task.Delay(1000);
+                    _navigationService.GoBack();
+                    return;
 
                 default:
                     AvailableVersions = new ObservableCollection(packageVersions.Versions!.Reverse());
diff --git a/src/PipManager/ViewModels/Pages/Search/SearchViewModel.cs b/src/ViewModels/Pages/Search/SearchViewModel.cs
similarity index 89%
rename from src/PipManager/ViewModels/Pages/Search/SearchViewModel.cs
rename to src/ViewModels/Pages/Search/SearchViewModel.cs
index 2361be0..423681e 100644
--- a/src/PipManager/ViewModels/Pages/Search/SearchViewModel.cs
+++ b/src/ViewModels/Pages/Search/SearchViewModel.cs
@@ -1,17 +1,17 @@
 using CommunityToolkit.Mvvm.Messaging;
-using PipManager.Languages;
-using PipManager.PackageSearch;
-using PipManager.PackageSearch.Wrappers.Query;
-using PipManager.Services.Mask;
-using PipManager.Services.Toast;
-using PipManager.Views.Pages.Search;
 using Serilog;
 using System.Collections.ObjectModel;
+using PipManager.Core.Services.PackageSearchService;
+using PipManager.Core.Wrappers.PackageSearchQueryWrapper;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Services.Mask;
+using PipManager.Windows.Services.Toast;
+using PipManager.Windows.Views.Pages.Search;
 using Wpf.Ui;
 using Wpf.Ui.Controls;
-using static PipManager.ViewModels.Pages.Search.SearchDetailViewModel;
+using static PipManager.Windows.ViewModels.Pages.Search.SearchDetailViewModel;
 
-namespace PipManager.ViewModels.Pages.Search;
+namespace PipManager.Windows.ViewModels.Pages.Search;
 
 public partial class SearchViewModel(IPackageSearchService packageSearchService, IToastService toastService, IMaskService maskService, INavigationService navigationService) : ObservableObject, INavigationAware
 {
@@ -67,7 +67,7 @@ private void ToDetailPage(object parameter)
     {
         navigationService.Navigate(typeof(SearchDetailPage));
         var current = QueryList.Where(searchListItem => searchListItem.Name == parameter as string).ToList()[0];
-        WeakReferenceMessenger.Default.Send(new SearchDetailMessage(current));
+        WeakReferenceMessenger.Default.Send(new SearchDetailViewModel.SearchDetailMessage(current));
         Log.Information($"[Search] Turn to detail page: {current.Name}");
     }
 
diff --git a/src/PipManager/ViewModels/Pages/Settings/SettingsViewModel.cs b/src/ViewModels/Pages/Settings/SettingsViewModel.cs
similarity index 93%
rename from src/PipManager/ViewModels/Pages/Settings/SettingsViewModel.cs
rename to src/ViewModels/Pages/Settings/SettingsViewModel.cs
index ffe0275..f13d5a8 100644
--- a/src/PipManager/ViewModels/Pages/Settings/SettingsViewModel.cs
+++ b/src/ViewModels/Pages/Settings/SettingsViewModel.cs
@@ -1,22 +1,22 @@
 using Newtonsoft.Json;
-using PipManager.Languages;
-using PipManager.Models;
-using PipManager.Models.Package;
-using PipManager.Services.Configuration;
-using PipManager.Services.Toast;
-using PipManager.Views.Pages.About;
-using PipManager.Views.Pages.Settings;
 using Serilog;
 using System.Diagnostics;
 using System.Globalization;
 using System.IO;
 using System.Net.Http;
+using PipManager.Windows.Languages;
+using PipManager.Windows.Models;
+using PipManager.Windows.Models.Package;
+using PipManager.Windows.Services.Configuration;
+using PipManager.Windows.Services.Toast;
+using PipManager.Windows.Views.Pages.About;
+using PipManager.Windows.Views.Pages.Settings;
 using Wpf.Ui;
 using Wpf.Ui.Appearance;
 using Wpf.Ui.Controls;
 using Wpf.Ui.Extensions;
 
-namespace PipManager.ViewModels.Pages.Settings;
+namespace PipManager.Windows.ViewModels.Pages.Settings;
 
 public partial class SettingsViewModel : ObservableObject, INavigationAware
 {
@@ -58,6 +58,7 @@ public void OnNavigatedFrom()
     private void InitializeViewModel()
     {
         CurrentPackageSource = _configurationService.AppConfig.PackageSource.PackageSourceType;
+        DetectNonReleaseVersion = _configurationService.AppConfig.PackageSource.DetectNonReleaseVersion;
         var language = _configurationService.AppConfig.Personalization.Language;
         Language = language != "Auto" ? GetLanguage.LanguageList.Select(x => x.Key).ToList()[GetLanguage.LanguageList.Select(x => x.Value).ToList().IndexOf(language)] : "Auto";
         CurrentTheme = _configurationService.AppConfig.Personalization.Theme switch
@@ -162,6 +163,17 @@ async Task DoubanTask()
         await Task.WhenAll(OfficialTask(), TsinghuaTask(), AliyunTask(), DoubanTask());
         Log.Information($"[Settings] Package Source network tested: Official({OfficialPackageSourceNetwork}) Tsinghua({TsinghuaPackageSourceNetwork}) Aliyun({AliyunPackageSourceNetwork}) Douban({DoubanPackageSourceNetwork})");
     }
+    
+    [ObservableProperty]
+    private bool _detectNonReleaseVersion;
+    
+    [RelayCommand]
+    private void OnChangeDetectNonReleaseVersion()
+    {
+        _configurationService.AppConfig.PackageSource.DetectNonReleaseVersion = DetectNonReleaseVersion;
+        _configurationService.Save();
+        Log.Information($"[Settings] Detect non-release update changes to {DetectNonReleaseVersion}");
+    }
 
     #endregion Package Source
 
diff --git a/src/PipManager/ViewModels/Pages/Tools/ToolsViewModel.cs b/src/ViewModels/Pages/Tools/ToolsViewModel.cs
similarity index 90%
rename from src/PipManager/ViewModels/Pages/Tools/ToolsViewModel.cs
rename to src/ViewModels/Pages/Tools/ToolsViewModel.cs
index 1b8d115..087acff 100644
--- a/src/PipManager/ViewModels/Pages/Tools/ToolsViewModel.cs
+++ b/src/ViewModels/Pages/Tools/ToolsViewModel.cs
@@ -1,7 +1,7 @@
 using Serilog;
 using Wpf.Ui.Controls;
 
-namespace PipManager.ViewModels.Pages.Tools;
+namespace PipManager.Windows.ViewModels.Pages.Tools;
 
 public partial class ToolsViewModel : ObservableObject, INavigationAware
 {
diff --git a/src/PipManager/ViewModels/Windows/MainWindowViewModel.cs b/src/ViewModels/Windows/MainWindowViewModel.cs
similarity index 83%
rename from src/PipManager/ViewModels/Windows/MainWindowViewModel.cs
rename to src/ViewModels/Windows/MainWindowViewModel.cs
index 3ccc622..e9faaac 100644
--- a/src/PipManager/ViewModels/Windows/MainWindowViewModel.cs
+++ b/src/ViewModels/Windows/MainWindowViewModel.cs
@@ -1,7 +1,7 @@
-using PipManager.Services.Configuration;
+using PipManager.Windows.Services.Configuration;
 using Serilog;
 
-namespace PipManager.ViewModels.Windows;
+namespace PipManager.Windows.ViewModels.Windows;
 
 public partial class MainWindowViewModel : ObservableObject
 {
@@ -9,6 +9,7 @@ public partial class MainWindowViewModel : ObservableObject
 
     public MainWindowViewModel(IConfigurationService configurationService)
     {
+
         if (configurationService.AppConfig.CurrentEnvironment != null)
         {
             Log.Information($"[MainWindow] Environment loaded ({configurationService.AppConfig.CurrentEnvironment.PipVersion} for {configurationService.AppConfig.CurrentEnvironment.PythonVersion})");
@@ -20,6 +21,9 @@ public MainWindowViewModel(IConfigurationService configurationService)
             ApplicationTitle = "Pip Manager";
         }
     }
+    
+    [ObservableProperty]
+    private bool _isTitleBarCoverageGridVisible;
 
     [ObservableProperty]
     private string _applicationTitle = "Pip Manager";
diff --git a/src/PipManager/Views/Pages/About/AboutPage.xaml b/src/Views/Pages/About/AboutPage.xaml
similarity index 89%
rename from src/PipManager/Views/Pages/About/AboutPage.xaml
rename to src/Views/Pages/About/AboutPage.xaml
index e5472ed..88055a5 100644
--- a/src/PipManager/Views/Pages/About/AboutPage.xaml
+++ b/src/Views/Pages/About/AboutPage.xaml
@@ -1,23 +1,23 @@
 
+    x:Class="PipManager.Windows.Views.Pages.About.AboutPage"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:about="clr-namespace:PipManager.Windows.Views.Pages.About"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:lang="clr-namespace:PipManager.Windows.Languages"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:pages="clr-namespace:PipManager.Windows.Models.Pages"
+    xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
     
         
@@ -25,9 +25,9 @@
                 
                     
                         
+                            Source="pack://application:,,,/Assets/icon.png"
+                            Width="200" />
                         
                             
                                 
                                 
-                                
+                                
 
                             
                             
                                 
+                                    Text="{Binding ViewModel.AppVersion, StringFormat=Version: {0}}"
+                                    VerticalAlignment="Center" />
 
                             
                             
@@ -67,44 +67,44 @@
                                     
                                 
                                 
+                                    NavigateUri="https://github.com/AuroraZiling/PipManager.Windows" />
                                 
+                                    NavigateUri="https://github.com/AuroraZiling/PipManager.Windows/issues" />
                                 
                                 
+                                    NavigateUri="https://github.com/AuroraZiling/PipManager.Windows/discussions" />
                             
                         
                     
                     
                         
+                            HorizontalAlignment="Right"
+                            Margin="-5,3,0,0"
+                            NavigateUri="https://github.com/AuroraZiling/PipManager.Windows/blob/main/LICENSE" />
                         
                     
                 
@@ -112,13 +112,13 @@
 
             
                 
                 
+                    Foreground="OrangeRed"
+                    Margin="0,5,0,0">
                     
                     
                     
@@ -126,29 +126,29 @@
                     
                 
                 
                 
+                    Margin="0,10,0,0"
+                    ScrollViewer.HorizontalScrollBarVisibility="Disabled"
+                    VerticalAlignment="Stretch">
                     
                         
-                            
+                            
                                 
                                     
+                                        NavigateUri="{Binding LibraryUrl}"
+                                        VerticalAlignment="Center" />
                                     
                                         
+                                            Text="{Binding LibraryName}"
+                                            VerticalAlignment="Center" />
 
                                         
                                             
+{
+    public About_AboutViewModel ViewModel { get; }
+
+    public AboutPage(About_AboutViewModel viewModel)
+    {
+        ViewModel = viewModel;
+        DataContext = this;
+
+        InitializeComponent();
+    }
+}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Action/ActionExceptionPage.xaml b/src/Views/Pages/Action/ActionExceptionPage.xaml
similarity index 95%
rename from src/PipManager/Views/Pages/Action/ActionExceptionPage.xaml
rename to src/Views/Pages/Action/ActionExceptionPage.xaml
index 380a2b1..e7df20d 100644
--- a/src/PipManager/Views/Pages/Action/ActionExceptionPage.xaml
+++ b/src/Views/Pages/Action/ActionExceptionPage.xaml
@@ -1,5 +1,5 @@
 
diff --git a/src/Views/Pages/Action/ActionExceptionPage.xaml.cs b/src/Views/Pages/Action/ActionExceptionPage.xaml.cs
new file mode 100644
index 0000000..1399dc9
--- /dev/null
+++ b/src/Views/Pages/Action/ActionExceptionPage.xaml.cs
@@ -0,0 +1,18 @@
+using Wpf.Ui.Controls;
+using Action_ActionExceptionViewModel = PipManager.Windows.ViewModels.Pages.Action.ActionExceptionViewModel;
+using ActionExceptionViewModel = PipManager.Windows.ViewModels.Pages.Action.ActionExceptionViewModel;
+
+namespace PipManager.Windows.Views.Pages.Action;
+
+public partial class ActionExceptionPage : INavigableView
+{
+    public Action_ActionExceptionViewModel ViewModel { get; }
+
+    public ActionExceptionPage(Action_ActionExceptionViewModel viewModel)
+    {
+        ViewModel = viewModel;
+        DataContext = this;
+
+        InitializeComponent();
+    }
+}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Action/ActionPage.xaml b/src/Views/Pages/Action/ActionPage.xaml
similarity index 96%
rename from src/PipManager/Views/Pages/Action/ActionPage.xaml
rename to src/Views/Pages/Action/ActionPage.xaml
index beca245..50b627b 100644
--- a/src/PipManager/Views/Pages/Action/ActionPage.xaml
+++ b/src/Views/Pages/Action/ActionPage.xaml
@@ -1,5 +1,5 @@
 
 
diff --git a/src/Views/Pages/Action/ActionPage.xaml.cs b/src/Views/Pages/Action/ActionPage.xaml.cs
new file mode 100644
index 0000000..b8986e6
--- /dev/null
+++ b/src/Views/Pages/Action/ActionPage.xaml.cs
@@ -0,0 +1,18 @@
+using Wpf.Ui.Controls;
+using Action_ActionViewModel = PipManager.Windows.ViewModels.Pages.Action.ActionViewModel;
+using ActionViewModel = PipManager.Windows.ViewModels.Pages.Action.ActionViewModel;
+
+namespace PipManager.Windows.Views.Pages.Action;
+
+public partial class ActionPage : INavigableView
+{
+    public Action_ActionViewModel ViewModel { get; }
+
+    public ActionPage(Action_ActionViewModel viewModel)
+    {
+        ViewModel = viewModel;
+        DataContext = this;
+
+        InitializeComponent();
+    }
+}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Environment/AddEnvironmentPage.xaml b/src/Views/Pages/Environment/AddEnvironmentPage.xaml
similarity index 87%
rename from src/PipManager/Views/Pages/Environment/AddEnvironmentPage.xaml
rename to src/Views/Pages/Environment/AddEnvironmentPage.xaml
index ed65968..a75b6b2 100644
--- a/src/PipManager/Views/Pages/Environment/AddEnvironmentPage.xaml
+++ b/src/Views/Pages/Environment/AddEnvironmentPage.xaml
@@ -1,37 +1,37 @@
 
+    x:Class="PipManager.Windows.Views.Pages.Environment.AddEnvironmentPage"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:appConfigModels="clr-namespace:PipManager.Windows.Models.AppConfigModels"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:environment="clr-namespace:PipManager.Windows.Views.Pages.Environment"
+    xmlns:lang="clr-namespace:PipManager.Windows.Languages"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
     
         
             
                 
                     
                         
                         
                         
                             
+                                Margin="5,0,0,0"
+                                Text="{I18N {x:Static lang:LangKeys.EnvironmentAdd_EnvironmentVariable_Header}}"
+                                VerticalAlignment="Center" />
                             
+                                HorizontalAlignment="Right"
+                                Icon="{ui:SymbolIcon ArrowClockwise20}"
+                                VerticalAlignment="Center" />
                         
                         
-                        
+                        
                         
+                            VerticalAlignment="Stretch"
+                            Visibility="{Binding ViewModel.Loading, Converter={StaticResource InverseBoolToVisibility}}"
+                            x:Name="ByEnvironmentVariablesList">
                             
                                 
-                                    
+                                    
                                         
                                             
                                             
                                         
                                         
+                                            Source="../../../Assets/logo/python-logo-only.png"
+                                            Width="48" />
                                         
                                             
                                                 
@@ -118,21 +118,21 @@
                         
                     
                     
+                        HorizontalAlignment="Right"
+                        Icon="{ui:SymbolIcon Add20}"
+                        Margin="0,0,0,13"
+                        VerticalAlignment="Bottom" />
                 
             
             
                 
                     
                         
                         
                     
@@ -141,35 +141,35 @@
                     
                         
                         
+                            Text="{Binding ViewModel.PipCommand, UpdateSourceTrigger=PropertyChanged}"
+                            x:Name="ByPipCommandTextBox" />
 
                         
+                            Margin="0,10,0,0"
+                            Message="{I18N {x:Static lang:LangKeys.EnvironmentAdd_PipCommand_Notice}}"
+                            Title="{I18N {x:Static lang:LangKeys.Common_NoticeTitle_Notice}}" />
                     
                     
+                        IsEnabled="{Binding ElementName=ByPipCommandTextBox, Path=Text, Converter={StaticResource StringIsNotNullOrEmpty}}"
+                        Margin="0,0,0,13"
+                        VerticalAlignment="Bottom" />
                 
             
             
                 
                     
                         
                         
                     
@@ -185,31 +185,31 @@
                                     
                                 
                                 
+                                    Text="{Binding ViewModel.PythonPath}"
+                                    x:Name="ByPythonPathTextBox" />
 
                                 
+                                    Grid.Column="1"
+                                    Icon="{ui:SymbolIcon FolderOpen20}"
+                                    Margin="3,0,0,0" />
                             
                         
                     
 
                     
+                        IsEnabled="{Binding ElementName=ByPythonPathTextBox, Path=Text, Converter={StaticResource StringIsNotNullOrEmpty}}"
+                        Margin="0,0,0,13"
+                        VerticalAlignment="Bottom" />
                 
             
         
diff --git a/src/PipManager/Views/Pages/Environment/AddEnvironmentPage.xaml.cs b/src/Views/Pages/Environment/AddEnvironmentPage.xaml.cs
similarity index 74%
rename from src/PipManager/Views/Pages/Environment/AddEnvironmentPage.xaml.cs
rename to src/Views/Pages/Environment/AddEnvironmentPage.xaml.cs
index ff2102e..34d24f2 100644
--- a/src/PipManager/Views/Pages/Environment/AddEnvironmentPage.xaml.cs
+++ b/src/Views/Pages/Environment/AddEnvironmentPage.xaml.cs
@@ -1,7 +1,7 @@
-using PipManager.ViewModels.Pages.Environment;
+using PipManager.Windows.ViewModels.Pages.Environment;
 using Wpf.Ui.Controls;
 
-namespace PipManager.Views.Pages.Environment;
+namespace PipManager.Windows.Views.Pages.Environment;
 
 public partial class AddEnvironmentPage : INavigableView
 {
diff --git a/src/Views/Pages/Environment/EnvironmentPage.xaml b/src/Views/Pages/Environment/EnvironmentPage.xaml
new file mode 100644
index 0000000..1b26f81
--- /dev/null
+++ b/src/Views/Pages/Environment/EnvironmentPage.xaml
@@ -0,0 +1,99 @@
+
+
+    
+        
+            
+                
+                
+                
+                
+                
+            
+            
+                
+                    
+                        
+                            
+                                
+                                
+                                
+                            
+                            
+                            
+                                
+                                    
+                                    
+                                    
+                                
+
+                                
+                            
+                        
+                    
+                
+            
+        
+
+    
+
+
\ No newline at end of file
diff --git a/src/Views/Pages/Environment/EnvironmentPage.xaml.cs b/src/Views/Pages/Environment/EnvironmentPage.xaml.cs
new file mode 100644
index 0000000..cfe7f00
--- /dev/null
+++ b/src/Views/Pages/Environment/EnvironmentPage.xaml.cs
@@ -0,0 +1,18 @@
+using Wpf.Ui.Controls;
+using Environment_EnvironmentViewModel = PipManager.Windows.ViewModels.Pages.Environment.EnvironmentViewModel;
+using EnvironmentViewModel = PipManager.Windows.ViewModels.Pages.Environment.EnvironmentViewModel;
+
+namespace PipManager.Windows.Views.Pages.Environment;
+
+public partial class EnvironmentPage : INavigableView
+{
+    public Environment_EnvironmentViewModel ViewModel { get; }
+
+    public EnvironmentPage(Environment_EnvironmentViewModel viewModel)
+    {
+        ViewModel = viewModel;
+        DataContext = this;
+
+        InitializeComponent();
+    }
+}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Lab/LabPage.xaml b/src/Views/Pages/Lab/LabPage.xaml
similarity index 68%
rename from src/PipManager/Views/Pages/Lab/LabPage.xaml
rename to src/Views/Pages/Lab/LabPage.xaml
index 09b4493..e9b1dfe 100644
--- a/src/PipManager/Views/Pages/Lab/LabPage.xaml
+++ b/src/Views/Pages/Lab/LabPage.xaml
@@ -1,22 +1,18 @@
 
-
-    
-    
-
\ No newline at end of file
+    x:Class="PipManager.Windows.Views.Pages.Lab.LabPage"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:lab="clr-namespace:PipManager.Windows.Views.Pages.Lab"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" />
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Lab/LabPage.xaml.cs b/src/Views/Pages/Lab/LabPage.xaml.cs
similarity index 74%
rename from src/PipManager/Views/Pages/Lab/LabPage.xaml.cs
rename to src/Views/Pages/Lab/LabPage.xaml.cs
index a10bb5a..cf74467 100644
--- a/src/PipManager/Views/Pages/Lab/LabPage.xaml.cs
+++ b/src/Views/Pages/Lab/LabPage.xaml.cs
@@ -1,7 +1,7 @@
-using PipManager.ViewModels.Pages.Lab;
+using PipManager.Windows.ViewModels.Pages.Lab;
 using Wpf.Ui.Controls;
 
-namespace PipManager.Views.Pages.Lab;
+namespace PipManager.Windows.Views.Pages.Lab;
 
 public partial class LabPage : INavigableView
 {
diff --git a/src/PipManager/Views/Pages/Library/LibraryDetailPage.xaml b/src/Views/Pages/Library/LibraryDetailPage.xaml
similarity index 91%
rename from src/PipManager/Views/Pages/Library/LibraryDetailPage.xaml
rename to src/Views/Pages/Library/LibraryDetailPage.xaml
index 4029612..08c0808 100644
--- a/src/PipManager/Views/Pages/Library/LibraryDetailPage.xaml
+++ b/src/Views/Pages/Library/LibraryDetailPage.xaml
@@ -1,25 +1,25 @@
-
+
 
+    x:Class="PipManager.Windows.Views.Pages.Library.LibraryDetailPage"
+    x:Name="LibraryDetail"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:lang="clr-namespace:PipManager.Windows.Languages"
+    xmlns:library="clr-namespace:PipManager.Windows.Views.Pages.Library"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
     
         
@@ -27,26 +27,26 @@
                 
                     
                         
+                            Text="{Binding ViewModel.Package.Name, Mode=TwoWay}"
+                            VerticalAlignment="Center" />
                         
+                            VerticalAlignment="Center">
                             
                         
                     
 
                     
 
                 
             
-            
+            
                 
                     
                         
@@ -73,8 +73,8 @@
                                     ToolTip="{Binding Url}"
                                     Visibility="{Binding Url, Converter={StaticResource NullToVisibility}}" />
                                 
                             
@@ -87,9 +87,9 @@
                 
                     
                     
+                        Content="{Binding ViewModel.DevelopmentStatus}"
+                        HorizontalAlignment="Left" />
                     
                     
                         
diff --git a/src/Views/Pages/Library/LibraryDetailPage.xaml.cs b/src/Views/Pages/Library/LibraryDetailPage.xaml.cs
new file mode 100644
index 0000000..38c1081
--- /dev/null
+++ b/src/Views/Pages/Library/LibraryDetailPage.xaml.cs
@@ -0,0 +1,17 @@
+using Wpf.Ui.Controls;
+using Library_LibraryDetailViewModel = PipManager.Windows.ViewModels.Pages.Library.LibraryDetailViewModel;
+using LibraryDetailViewModel = PipManager.Windows.ViewModels.Pages.Library.LibraryDetailViewModel;
+
+namespace PipManager.Windows.Views.Pages.Library;
+
+public partial class LibraryDetailPage : INavigableView
+{
+    public Library_LibraryDetailViewModel ViewModel { get; }
+
+    public LibraryDetailPage(Library_LibraryDetailViewModel viewModel)
+    {
+        ViewModel = viewModel;
+        DataContext = this;
+        InitializeComponent();
+    }
+}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Library/LibraryInstallPage.xaml b/src/Views/Pages/Library/LibraryInstallPage.xaml
similarity index 98%
rename from src/PipManager/Views/Pages/Library/LibraryInstallPage.xaml
rename to src/Views/Pages/Library/LibraryInstallPage.xaml
index e327794..c678a99 100644
--- a/src/PipManager/Views/Pages/Library/LibraryInstallPage.xaml
+++ b/src/Views/Pages/Library/LibraryInstallPage.xaml
@@ -1,5 +1,5 @@
 
 
diff --git a/src/Views/Pages/Library/LibraryInstallPage.xaml.cs b/src/Views/Pages/Library/LibraryInstallPage.xaml.cs
new file mode 100644
index 0000000..3613bd8
--- /dev/null
+++ b/src/Views/Pages/Library/LibraryInstallPage.xaml.cs
@@ -0,0 +1,17 @@
+using Wpf.Ui.Controls;
+using Library_LibraryInstallViewModel = PipManager.Windows.ViewModels.Pages.Library.LibraryInstallViewModel;
+using LibraryInstallViewModel = PipManager.Windows.ViewModels.Pages.Library.LibraryInstallViewModel;
+
+namespace PipManager.Windows.Views.Pages.Library;
+
+public partial class LibraryInstallPage : INavigableView
+{
+    public Library_LibraryInstallViewModel ViewModel { get; }
+
+    public LibraryInstallPage(Library_LibraryInstallViewModel viewModel)
+    {
+        ViewModel = viewModel;
+        DataContext = this;
+        InitializeComponent();
+    }
+}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Library/LibraryPage.xaml b/src/Views/Pages/Library/LibraryPage.xaml
similarity index 80%
rename from src/PipManager/Views/Pages/Library/LibraryPage.xaml
rename to src/Views/Pages/Library/LibraryPage.xaml
index 008ded7..db44134 100644
--- a/src/PipManager/Views/Pages/Library/LibraryPage.xaml
+++ b/src/Views/Pages/Library/LibraryPage.xaml
@@ -1,5 +1,5 @@
 
 
@@ -85,6 +85,23 @@
                         
                     
                 
+                
+                    
+                        
+                            
+                                
+                                    
+                                
+                            
+                        
+                    
+                
                 
 
         
-                             
-                                 
-                                     
-                                         
-                                             
-                                             
+            Grid.Row="1"
+            IsTextSearchCaseSensitive="False"
+            IsTextSearchEnabled="True"
+            ItemsSource="{Binding ViewModel.LibraryList, Mode=TwoWay}"
+            Margin="0,10,0,0"
+            SelectionMode="Multiple"
+            TextSearch.TextPath="PackageName"
+            Visibility="{Binding ViewModel.LibraryList, Converter={StaticResource NotNullToVisibility}}"
+            x:Name="LibraryList">
+            
+                
+                    
+                        
+                            
+                            
                         
                         
                         
@@ -117,7 +134,7 @@
                                     Style="{StaticResource BodyLargeTextBlockStyle}"
                                     Text="{Binding PackageName}"
                                     VerticalAlignment="Center" />
-                                
+                                
                                     
                                         
                                     
@@ -130,7 +147,7 @@
                                     
                                         
                                     
-                                
+                                
 
                             
 
diff --git a/src/Views/Pages/Library/LibraryPage.xaml.cs b/src/Views/Pages/Library/LibraryPage.xaml.cs
new file mode 100644
index 0000000..c6593c1
--- /dev/null
+++ b/src/Views/Pages/Library/LibraryPage.xaml.cs
@@ -0,0 +1,17 @@
+using Wpf.Ui.Controls;
+using Library_LibraryViewModel = PipManager.Windows.ViewModels.Pages.Library.LibraryViewModel;
+using LibraryViewModel = PipManager.Windows.ViewModels.Pages.Library.LibraryViewModel;
+
+namespace PipManager.Windows.Views.Pages.Library;
+
+public partial class LibraryPage : INavigableView
+{
+    public Library_LibraryViewModel ViewModel { get; }
+
+    public LibraryPage(Library_LibraryViewModel viewModel)
+    {
+        ViewModel = viewModel;
+        DataContext = this;
+        InitializeComponent();
+    }
+}
\ No newline at end of file
diff --git a/src/Views/Pages/Overlay/OverlayPage.xaml b/src/Views/Pages/Overlay/OverlayPage.xaml
new file mode 100644
index 0000000..c8f24cd
--- /dev/null
+++ b/src/Views/Pages/Overlay/OverlayPage.xaml
@@ -0,0 +1,75 @@
+
+    
+        
+            
+            
+            
+        
+        
+        
+            
+                
+                    
+                        
+                            
+                                
+                                
+                                
+                            
+                            
+                            
+                                
+                                
+                                
+                            
+                        
+                    
+                
+            
+        
+        
+            
+            
+        
+    
+
diff --git a/src/PipManager/Views/Pages/Overlay/OverlayPage.xaml.cs b/src/Views/Pages/Overlay/OverlayPage.xaml.cs
similarity index 69%
rename from src/PipManager/Views/Pages/Overlay/OverlayPage.xaml.cs
rename to src/Views/Pages/Overlay/OverlayPage.xaml.cs
index f45a90a..0a01b6d 100644
--- a/src/PipManager/Views/Pages/Overlay/OverlayPage.xaml.cs
+++ b/src/Views/Pages/Overlay/OverlayPage.xaml.cs
@@ -1,6 +1,6 @@
-using PipManager.ViewModels.Pages.Overlay;
+using PipManager.Windows.ViewModels.Pages.Overlay;
 
-namespace PipManager.Views.Pages.Overlay;
+namespace PipManager.Windows.Views.Pages.Overlay;
 
 public partial class OverlayPage
 {
diff --git a/src/PipManager/Views/Pages/Search/SearchDetailPage.xaml b/src/Views/Pages/Search/SearchDetailPage.xaml
similarity index 89%
rename from src/PipManager/Views/Pages/Search/SearchDetailPage.xaml
rename to src/Views/Pages/Search/SearchDetailPage.xaml
index 81ac877..82ad857 100644
--- a/src/PipManager/Views/Pages/Search/SearchDetailPage.xaml
+++ b/src/Views/Pages/Search/SearchDetailPage.xaml
@@ -1,6 +1,6 @@
-
+
 
@@ -55,7 +55,11 @@
 
         
             
-                
+                
+                    
+                    
+                
+                
                     
                         
                 
                 
@@ -98,17 +103,17 @@
                         Width="150" />
                     
                     
                 
             
diff --git a/src/PipManager/Views/Pages/Search/SearchDetailPage.xaml.cs b/src/Views/Pages/Search/SearchDetailPage.xaml.cs
similarity index 69%
rename from src/PipManager/Views/Pages/Search/SearchDetailPage.xaml.cs
rename to src/Views/Pages/Search/SearchDetailPage.xaml.cs
index 5ef7642..90b5e7e 100644
--- a/src/PipManager/Views/Pages/Search/SearchDetailPage.xaml.cs
+++ b/src/Views/Pages/Search/SearchDetailPage.xaml.cs
@@ -1,17 +1,18 @@
 using Microsoft.Web.WebView2.Core;
 using Microsoft.Web.WebView2.Wpf;
 using Wpf.Ui.Controls;
-using SearchDetailViewModel = PipManager.ViewModels.Pages.Search.SearchDetailViewModel;
+using Search_SearchDetailViewModel = PipManager.Windows.ViewModels.Pages.Search.SearchDetailViewModel;
+using SearchDetailViewModel = PipManager.Windows.ViewModels.Pages.Search.SearchDetailViewModel;
 
-namespace PipManager.Views.Pages.Search;
+namespace PipManager.Windows.Views.Pages.Search;
 
-public partial class SearchDetailPage : INavigableView
+public partial class SearchDetailPage : INavigableView
 {
     public static WebView2? ProjectDescriptionWebView { get; private set; }
 
-    public SearchDetailViewModel ViewModel { get; }
+    public Search_SearchDetailViewModel ViewModel { get; }
 
-    public SearchDetailPage(SearchDetailViewModel viewModel)
+    public SearchDetailPage(Search_SearchDetailViewModel viewModel)
     {
         ViewModel = viewModel;
         DataContext = this;
diff --git a/src/PipManager/Views/Pages/Search/SearchPage.xaml b/src/Views/Pages/Search/SearchPage.xaml
similarity index 93%
rename from src/PipManager/Views/Pages/Search/SearchPage.xaml
rename to src/Views/Pages/Search/SearchPage.xaml
index f9cba8d..992c04f 100644
--- a/src/PipManager/Views/Pages/Search/SearchPage.xaml
+++ b/src/Views/Pages/Search/SearchPage.xaml
@@ -1,5 +1,5 @@
 
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:query="clr-namespace:PipManager.Core.Wrappers.PackageSearchQueryWrapper;assembly=PipManager.Core">
 
     
         
diff --git a/src/PipManager/Views/Pages/Search/SearchPage.xaml.cs b/src/Views/Pages/Search/SearchPage.xaml.cs
similarity index 74%
rename from src/PipManager/Views/Pages/Search/SearchPage.xaml.cs
rename to src/Views/Pages/Search/SearchPage.xaml.cs
index 60446fa..0ce1a3e 100644
--- a/src/PipManager/Views/Pages/Search/SearchPage.xaml.cs
+++ b/src/Views/Pages/Search/SearchPage.xaml.cs
@@ -1,7 +1,7 @@
-using PipManager.ViewModels.Pages.Search;
+using PipManager.Windows.ViewModels.Pages.Search;
 using Wpf.Ui.Controls;
 
-namespace PipManager.Views.Pages.Search;
+namespace PipManager.Windows.Views.Pages.Search;
 
 public partial class SearchPage : INavigableView
 {
diff --git a/src/PipManager/Views/Pages/Settings/SettingsPage.xaml b/src/Views/Pages/Settings/SettingsPage.xaml
similarity index 93%
rename from src/PipManager/Views/Pages/Settings/SettingsPage.xaml
rename to src/Views/Pages/Settings/SettingsPage.xaml
index 899bba2..c2e4f7c 100644
--- a/src/PipManager/Views/Pages/Settings/SettingsPage.xaml
+++ b/src/Views/Pages/Settings/SettingsPage.xaml
@@ -1,5 +1,5 @@
 
     
@@ -28,9 +28,9 @@
         
         
             
-                
+                
 
-                
+                
                 
                     
                         
@@ -133,6 +133,28 @@
                             Margin="0,10,0,0" />
                     
                 
+
+                
+                
+                    
+                        
+                            
+                                
+                                
+                            
+                            
+                            
+                        
+                    
+                    
+                
             
         
 
diff --git a/src/Views/Pages/Settings/SettingsPage.xaml.cs b/src/Views/Pages/Settings/SettingsPage.xaml.cs
new file mode 100644
index 0000000..52bf9f4
--- /dev/null
+++ b/src/Views/Pages/Settings/SettingsPage.xaml.cs
@@ -0,0 +1,18 @@
+using Wpf.Ui.Controls;
+using Settings_SettingsViewModel = PipManager.Windows.ViewModels.Pages.Settings.SettingsViewModel;
+using SettingsViewModel = PipManager.Windows.ViewModels.Pages.Settings.SettingsViewModel;
+
+namespace PipManager.Windows.Views.Pages.Settings;
+
+public partial class SettingsPage : INavigableView
+{
+    public Settings_SettingsViewModel ViewModel { get; }
+
+    public SettingsPage(Settings_SettingsViewModel viewModel)
+    {
+        ViewModel = viewModel;
+        DataContext = this;
+
+        InitializeComponent();
+    }
+}
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Tools/ToolsPage.xaml b/src/Views/Pages/Tools/ToolsPage.xaml
similarity index 70%
rename from src/PipManager/Views/Pages/Tools/ToolsPage.xaml
rename to src/Views/Pages/Tools/ToolsPage.xaml
index 882e935..0dedce7 100644
--- a/src/PipManager/Views/Pages/Tools/ToolsPage.xaml
+++ b/src/Views/Pages/Tools/ToolsPage.xaml
@@ -1,22 +1,22 @@
 
+    x:Class="PipManager.Windows.Views.Pages.Tools.ToolsPage"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:tools="clr-namespace:PipManager.Windows.Views.Pages.Tools"
+    xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
     
 
\ No newline at end of file
diff --git a/src/PipManager/Views/Pages/Tools/ToolsPage.xaml.cs b/src/Views/Pages/Tools/ToolsPage.xaml.cs
similarity index 74%
rename from src/PipManager/Views/Pages/Tools/ToolsPage.xaml.cs
rename to src/Views/Pages/Tools/ToolsPage.xaml.cs
index 1eccaf9..d21c3c6 100644
--- a/src/PipManager/Views/Pages/Tools/ToolsPage.xaml.cs
+++ b/src/Views/Pages/Tools/ToolsPage.xaml.cs
@@ -1,7 +1,7 @@
-using PipManager.ViewModels.Pages.Tools;
+using PipManager.Windows.ViewModels.Pages.Tools;
 using Wpf.Ui.Controls;
 
-namespace PipManager.Views.Pages.Tools;
+namespace PipManager.Windows.Views.Pages.Tools;
 
 public partial class ToolsPage : INavigableView
 {
diff --git a/src/PipManager/Views/Windows/ExceptionWindow.xaml b/src/Views/Windows/ExceptionWindow.xaml
similarity index 76%
rename from src/PipManager/Views/Windows/ExceptionWindow.xaml
rename to src/Views/Windows/ExceptionWindow.xaml
index 2105b91..ca45068 100644
--- a/src/PipManager/Views/Windows/ExceptionWindow.xaml
+++ b/src/Views/Windows/ExceptionWindow.xaml
@@ -1,25 +1,25 @@
 
+    d:DataContext="{d:DesignInstance local:ExceptionWindow,
+                                     IsDesignTimeCreatable=True}"
+    mc:Ignorable="d"
+    x:Class="PipManager.Windows.Views.Windows.ExceptionWindow"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:lang="clr-namespace:PipManager.Windows.Languages"
+    xmlns:local="clr-namespace:PipManager.Windows.Views.Windows"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     
         
             
@@ -27,17 +27,17 @@
             
         
         
+            Grid.Row="0"
+            ShowMaximize="False"
+            Title="{I18N {x:Static lang:LangKeys.ExceptionWindow_Title}}"
+            x:Name="TitleBar">
             
                 
+                    Source="pack://application:,,,/Assets/icon.png"
+                    Width="22" />
             
         
         
                 
                 
+                    x:Name="TypeTextBlock" />
             
             
                 
                 
+                    TextWrapping="WrapWithOverflow"
+                    VerticalAlignment="Center"
+                    x:Name="MessageTextBlock" />
             
         
         
             
             
+                x:Name="StackTraceTextBox" />
             
+                HorizontalAlignment="Stretch"
+                Icon="{ui:SymbolIcon Bug24}"
+                VerticalAlignment="Bottom"
+                x:Name="ReportButton" />
         
     
 
\ No newline at end of file
diff --git a/src/PipManager/Views/Windows/ExceptionWindow.xaml.cs b/src/Views/Windows/ExceptionWindow.xaml.cs
similarity index 88%
rename from src/PipManager/Views/Windows/ExceptionWindow.xaml.cs
rename to src/Views/Windows/ExceptionWindow.xaml.cs
index f474603..3dfb431 100644
--- a/src/PipManager/Views/Windows/ExceptionWindow.xaml.cs
+++ b/src/Views/Windows/ExceptionWindow.xaml.cs
@@ -1,6 +1,6 @@
 using System.Diagnostics;
 
-namespace PipManager.Views.Windows;
+namespace PipManager.Windows.Views.Windows;
 
 /// 
 /// ExceptionWindow.xaml 的交互逻辑
@@ -24,6 +24,6 @@ public void Initialize(Exception exception)
 
     private void ReportButton_OnClick(object sender, RoutedEventArgs e)
     {
-        Process.Start("explorer.exe", "https://github.com/Pip-Manager/PipManager/issues/new");
+        Process.Start("explorer.exe", "https://github.com/Pip-Manager/PipManager.Windows/issues/new");
     }
 }
\ No newline at end of file
diff --git a/src/PipManager/Views/Windows/MainWindow.xaml b/src/Views/Windows/MainWindow.xaml
similarity index 78%
rename from src/PipManager/Views/Windows/MainWindow.xaml
rename to src/Views/Windows/MainWindow.xaml
index 1c0d1c6..3e01912 100644
--- a/src/PipManager/Views/Windows/MainWindow.xaml
+++ b/src/Views/Windows/MainWindow.xaml
@@ -1,7 +1,7 @@
 
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
     
         
@@ -99,8 +99,8 @@
             Grid.Row="0"
             Grid.RowSpan="2"
             x:Name="MaskPresenter" />
-        
-        
+
+        
 
         
 
         
             
                 
             
         
-        
-        
-        
-        
+
+        
+        
+
         
-
-#Disable inspections
-#exclude:
-#  - name: 
-#    paths:
-#      - 
-
-#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
-#bootstrap: sh ./prepare-qodana.sh
-
-#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
-#plugins:
-#  - id:  #(plugin id can be found at https://plugins.jetbrains.com)
-
-#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
-linter: jetbrains/qodana-dotnet:latest