├── logo.png ├── .gitattributes ├── WSATools ├── WSATools │ ├── favicon.ico │ ├── FodyWeavers.xml │ ├── Properties │ │ ├── launchSettings.json │ │ ├── Settings.settings │ │ └── Settings.Designer.cs │ ├── Helpers │ │ ├── Converter │ │ │ ├── IsEqualToVisibilityConverter.cs │ │ │ ├── BoolToVisibilityConverter.cs │ │ │ ├── ConverterTools.cs │ │ │ ├── IsEqualToObjectConverter.cs │ │ │ └── BoolToObjectConverter.cs │ │ ├── UpdateHelper.cs │ │ └── UIHelper.cs │ ├── Themes │ │ ├── Generic.xaml │ │ ├── SettingsUI.xaml │ │ ├── Dark │ │ │ └── Color.xaml │ │ ├── Light │ │ │ └── Color.xaml │ │ └── HighContrast │ │ │ └── Color.xaml │ ├── Pages │ │ ├── SettingsPages │ │ │ ├── TestPage.xaml.cs │ │ │ ├── TestPage.xaml │ │ │ ├── SettingsPage.xaml.cs │ │ │ └── SettingsPage.xaml │ │ ├── AppsPage.xaml.cs │ │ ├── AppsPage.xaml │ │ ├── HomePage.xaml.cs │ │ ├── MainPage.xaml │ │ ├── HomePage.xaml │ │ └── MainPage.xaml.cs │ ├── MainWindow.xaml.cs │ ├── MainWindow.xaml │ ├── AssemblyInfo.cs │ ├── Styles │ │ ├── TextBlock.xaml │ │ ├── SettingButton.xaml │ │ ├── SettingsGroup.xaml │ │ ├── Button.xaml │ │ ├── Setting.xaml │ │ └── SettingExpander.xaml │ ├── ViewModels │ │ ├── AppsViewModel.cs │ │ ├── HomeViewModel.cs │ │ └── SettingsViewModel.cs │ ├── Models │ │ ├── UpdateInfo.cs │ │ └── SystemVersionInfo.cs │ ├── App.xaml.cs │ ├── App.xaml │ ├── Controls │ │ ├── SettingsGroup.cs │ │ ├── PageHeader.xaml │ │ ├── PageHeader.xaml.cs │ │ └── Setting.cs │ ├── WSATools.csproj │ └── FodyWeavers.xsd ├── WSATools.Package │ ├── Images │ │ ├── StoreLogo.backup.png │ │ ├── LargeTile.scale-100.png │ │ ├── LargeTile.scale-125.png │ │ ├── LargeTile.scale-150.png │ │ ├── LargeTile.scale-200.png │ │ ├── LargeTile.scale-400.png │ │ ├── SmallTile.scale-100.png │ │ ├── SmallTile.scale-125.png │ │ ├── SmallTile.scale-150.png │ │ ├── SmallTile.scale-200.png │ │ ├── SmallTile.scale-400.png │ │ ├── StoreLogo.scale-100.png │ │ ├── StoreLogo.scale-125.png │ │ ├── StoreLogo.scale-150.png │ │ ├── StoreLogo.scale-200.png │ │ ├── StoreLogo.scale-400.png │ │ ├── SplashScreen.scale-100.png │ │ ├── SplashScreen.scale-125.png │ │ ├── SplashScreen.scale-150.png │ │ ├── SplashScreen.scale-200.png │ │ ├── SplashScreen.scale-400.png │ │ ├── LockScreenLogo.scale-200.png │ │ ├── Square44x44Logo.scale-100.png │ │ ├── Square44x44Logo.scale-125.png │ │ ├── Square44x44Logo.scale-150.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Square44x44Logo.scale-400.png │ │ ├── Wide310x150Logo.scale-100.png │ │ ├── Wide310x150Logo.scale-125.png │ │ ├── Wide310x150Logo.scale-150.png │ │ ├── Wide310x150Logo.scale-200.png │ │ ├── Wide310x150Logo.scale-400.png │ │ ├── Square150x150Logo.scale-100.png │ │ ├── Square150x150Logo.scale-125.png │ │ ├── Square150x150Logo.scale-150.png │ │ ├── Square150x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-400.png │ │ ├── Square44x44Logo.targetsize-16.png │ │ ├── Square44x44Logo.targetsize-24.png │ │ ├── Square44x44Logo.targetsize-256.png │ │ ├── Square44x44Logo.targetsize-32.png │ │ ├── Square44x44Logo.targetsize-48.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-48.png │ │ └── Square44x44Logo.altform-lightunplated_targetsize-256.png │ ├── Package.appxmanifest │ └── WSATools.Package.wapproj └── WSATools.Core │ ├── Models │ ├── StorageInfo.cs │ └── APKInfo.cs │ ├── WSATools.Core.csproj │ ├── Helpers │ ├── WSAHelper.cs │ └── ADBHelper.cs │ └── Receivers │ └── StorageReceiver.cs ├── .gitmodules ├── .github ├── FUNDING.yml └── workflows │ └── build-and-publish.yml ├── README.md ├── .gitignore └── WSATools.sln /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/logo.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /WSATools/WSATools/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools/favicon.ico -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "WSATools/APPXManager"] 2 | path = WSATools/APPXManager 3 | url = https://github.com/wherewhere/APPX-Manager.git 4 | -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/StoreLogo.backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/StoreLogo.backup.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/LargeTile.scale-100.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/LargeTile.scale-125.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/LargeTile.scale-150.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/LargeTile.scale-200.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/LargeTile.scale-400.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/SmallTile.scale-100.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/SmallTile.scale-125.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/SmallTile.scale-150.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/SmallTile.scale-200.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/SmallTile.scale-400.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /WSATools/WSATools/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Wide310x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Wide310x150Logo.scale-100.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Wide310x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Wide310x150Logo.scale-125.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Wide310x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Wide310x150Logo.scale-150.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Wide310x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Wide310x150Logo.scale-400.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /WSATools/WSATools/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "WSATools": { 4 | "commandName": "Project", 5 | "nativeDebugging": true 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.altform-unplated_targetsize-16.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.altform-unplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.altform-unplated_targetsize-32.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.altform-unplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.altform-lightunplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.altform-lightunplated_targetsize-16.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.altform-lightunplated_targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.altform-lightunplated_targetsize-24.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.altform-lightunplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.altform-lightunplated_targetsize-32.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.altform-lightunplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.altform-lightunplated_targetsize-48.png -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Images/Square44x44Logo.altform-lightunplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paving-Base/WSA-Tools/HEAD/WSATools/WSATools.Package/Images/Square44x44Logo.altform-lightunplated_targetsize-256.png -------------------------------------------------------------------------------- /WSATools/WSATools.Core/Models/StorageInfo.cs: -------------------------------------------------------------------------------- 1 | namespace WSATools.Core.Models 2 | { 3 | public class StorageInfo 4 | { 5 | public int Use { get; set; } 6 | public int Size { get; set; } 7 | public int Used { get; set; } 8 | public int Available { get; set; } 9 | public string Mountedon { get; set; } 10 | public string Filesystem { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /WSATools/WSATools/Helpers/Converter/IsEqualToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace WSATools.Helpers.Converter 4 | { 5 | public partial class IsEqualToVisibilityConverter : IsEqualToObjectConverter 6 | { 7 | public IsEqualToVisibilityConverter() 8 | { 9 | TrueValue = Visibility.Visible; 10 | FalseValue = Visibility.Collapsed; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WSATools/WSATools/Themes/Generic.xaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WSATools/WSATools.Core/Models/APKInfo.cs: -------------------------------------------------------------------------------- 1 | using AdvancedSharpAdbClient.DeviceCommands; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WSATools.Core.Models 9 | { 10 | public class APKInfo 11 | { 12 | public string Name { get; set; } 13 | public bool IsActive { get; set; } 14 | public VersionInfo VersionInfo { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /WSATools/WSATools/Pages/SettingsPages/TestPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Controls; 3 | using Windows.Foundation.Collections; 4 | using Windows.System; 5 | 6 | namespace WSATools.Pages.SettingsPages 7 | { 8 | /// 9 | /// TestPage.xaml 的交互逻辑 10 | /// 11 | public partial class TestPage : Page 12 | { 13 | public TestPage() 14 | { 15 | InitializeComponent(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WSATools/WSATools/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 2021-11-12 7 | 8 | 9 | -------------------------------------------------------------------------------- /WSATools/WSATools/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using WSATools.Helpers; 3 | using WSATools.Pages; 4 | 5 | namespace WSATools 6 | { 7 | /// 8 | /// Interaction logic for MainWindow.xaml 9 | /// 10 | public partial class MainWindow : Window 11 | { 12 | public MainWindow() 13 | { 14 | InitializeComponent(); 15 | UIHelper.MainWindow = this; 16 | MainPage MainPage = new(); 17 | Content = MainPage; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /WSATools/WSATools/Pages/SettingsPages/TestPage.xaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /WSATools/WSATools/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /WSATools/WSATools/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /WSATools/WSATools.Core/WSATools.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | preview 5 | net4.8 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WSATools/WSATools/Helpers/Converter/BoolToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace WSATools.Helpers.Converter 4 | { 5 | /// 6 | /// This class converts a boolean value into a Visibility enumeration. 7 | /// 8 | public class BoolToVisibilityConverter : BoolToObjectConverter 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public BoolToVisibilityConverter() 14 | { 15 | TrueValue = Visibility.Visible; 16 | FalseValue = Visibility.Collapsed; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /WSATools/WSATools/Pages/AppsPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace WSATools.Pages 17 | { 18 | /// 19 | /// AppsPage.xaml 的交互逻辑 20 | /// 21 | public partial class AppsPage : ModernWpf.Controls.Page 22 | { 23 | public AppsPage() => InitializeComponent(); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: wherewhere 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: ['afdian.net/@wherewhere'] 14 | -------------------------------------------------------------------------------- /WSATools/WSATools/Pages/SettingsPages/SettingsPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using ModernWpf.Controls; 2 | using System.Windows.Navigation; 3 | using WSATools.ViewModels; 4 | 5 | namespace WSATools.Pages.SettingsPages 6 | { 7 | /// 8 | /// SettingsPage.xaml 的交互逻辑 9 | /// 10 | public partial class SettingsPage : Page 11 | { 12 | private SettingsViewModel ViewModel; 13 | 14 | public SettingsPage() 15 | { 16 | InitializeComponent(); 17 | } 18 | 19 | protected override void OnNavigatedTo(NavigationEventArgs e) 20 | { 21 | base.OnNavigatedTo(e); 22 | if (DataContext is SettingsViewModel viewModel) 23 | { 24 | ViewModel = viewModel; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /WSATools/WSATools/Pages/AppsPage.xaml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /WSATools/WSATools/Themes/SettingsUI.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 240 12 | -------------------------------------------------------------------------------- /WSATools/WSATools.Core/Helpers/WSAHelper.cs: -------------------------------------------------------------------------------- 1 | using APPXManager.DeviceCommands; 2 | using APPXManager.Models; 3 | using System.Diagnostics; 4 | 5 | namespace WSATools.Core.Helpers 6 | { 7 | public static class WSAHelper 8 | { 9 | public static bool IsWSARunning 10 | { 11 | get 12 | { 13 | Process[] ps = Process.GetProcessesByName("vmmemWSA"); 14 | return ps != null && ps.Length > 0; 15 | } 16 | } 17 | 18 | public static (bool, PackageInfo) GetWSAInfo() => PackageManager.FindPackageByName("MicrosoftCorporationII.WindowsSubsystemForAndroid"); 19 | 20 | public static void StartWSA() 21 | { 22 | PackageManager.LaunchPackage("MicrosoftCorporationII.WindowsSubsystemForAndroid_8wekyb3d8bbwe"); 23 | while (IsWSARunning) 24 | { 25 | ; 26 | } 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WSATools/WSATools/Themes/Dark/Color.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 1 9 | #FF5fb2f2 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /WSATools/WSATools/Themes/Light/Color.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 1 9 | #FF0063b1 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /WSATools/WSATools/Themes/HighContrast/Color.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 2 9 | #FF5fb2f2 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /WSATools/WSATools/Pages/HomePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using ModernWpf.Controls; 2 | using System.Security.Principal; 3 | using System.Windows; 4 | using System.Windows.Navigation; 5 | using WSATools.ViewModels; 6 | 7 | namespace WSATools.Pages 8 | { 9 | /// 10 | /// HomePage.xaml 的交互逻辑 11 | /// 12 | public partial class HomePage : Page 13 | { 14 | private HomeViewModel Provider; 15 | 16 | public HomePage() 17 | { 18 | InitializeComponent(); 19 | } 20 | 21 | protected override void OnNavigatedTo(NavigationEventArgs e) 22 | { 23 | base.OnNavigatedTo(e); 24 | if (DataContext is HomeViewModel ViewModel) 25 | { 26 | Provider = ViewModel; 27 | } 28 | //获得当前登录的Windows用户标示 29 | WindowsIdentity identity = WindowsIdentity.GetCurrent(); 30 | WindowsPrincipal principal = new WindowsPrincipal(identity); 31 | InfoBar.Visibility = principal.IsInRole(WindowsBuiltInRole.Administrator) ? Visibility.Collapsed : Visibility.Visible; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /WSATools/WSATools/Styles/TextBlock.xaml: -------------------------------------------------------------------------------- 1 | 6 | 16 | 12 17 | 21 | -------------------------------------------------------------------------------- /WSATools/WSATools/ViewModels/AppsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using WSATools.Core.Helpers; 9 | using WSATools.Core.Models; 10 | 11 | namespace WSATools.ViewModels 12 | { 13 | public sealed class AppsViewModel : INotifyPropertyChanged 14 | { 15 | ObservableCollection _appList; 16 | public ObservableCollection AppList 17 | { 18 | get => _appList; 19 | set 20 | { 21 | if (_appList != value) 22 | { 23 | _appList = value; 24 | RaisePropertyChangedEvent(); 25 | } 26 | } 27 | } 28 | 29 | public event PropertyChangedEventHandler PropertyChanged; 30 | 31 | private void RaisePropertyChangedEvent([System.Runtime.CompilerServices.CallerMemberName] string name = null) 32 | { 33 | if (name != null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } 34 | } 35 | 36 | public void Refresh() 37 | { 38 | AppList = ADBHelper.GetAppsList(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /WSATools/WSATools/Helpers/Converter/ConverterTools.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace WSATools.Helpers.Converter 4 | { 5 | /// 6 | /// Static class used to provide internal tools 7 | /// 8 | internal static class ConverterTools 9 | { 10 | /// 11 | /// Helper method to safely cast an object to a boolean 12 | /// 13 | /// Parameter to cast to a boolean 14 | /// Bool value or false if cast failed 15 | internal static bool TryParseBool(object parameter) 16 | { 17 | bool parsed = false; 18 | if (parameter != null) 19 | { 20 | bool.TryParse(parameter.ToString(), out parsed); 21 | } 22 | 23 | return parsed; 24 | } 25 | 26 | /// 27 | /// Helper method to convert a value from a source type to a target type. 28 | /// 29 | /// The value to convert 30 | /// The target type 31 | /// The converted value 32 | internal static object Convert(object value, Type targetType) 33 | { 34 | return value; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /WSATools/WSATools/Models/UpdateInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace WSATools.Models 6 | { 7 | public class UpdateInfo 8 | { 9 | [JsonPropertyName("url")] 10 | public string ApiUrl { get; set; } 11 | [JsonPropertyName("html_url")] 12 | public string ReleaseUrl { get; set; } 13 | [JsonPropertyName("tag_name")] 14 | public string TagName { get; set; } 15 | [JsonPropertyName("prerelease")] 16 | public bool IsPreRelease { get; set; } 17 | [JsonPropertyName("created_at")] 18 | public DateTime CreatedAt { get; set; } 19 | [JsonPropertyName("published_at")] 20 | public DateTime PublishedAt { get; set; } 21 | [JsonPropertyName("assets")] 22 | public List Assets { get; set; } 23 | [JsonPropertyName("body")] 24 | public string Changelog { get; set; } 25 | public bool IsExistNewVersion { get; set; } 26 | public UpdateState UpdateState { get; set; } 27 | } 28 | 29 | public class Asset 30 | { 31 | [JsonPropertyName("size")] 32 | public int Size { get; set; } 33 | [JsonPropertyName("browser_download_url")] 34 | public string Url { get; set; } 35 | } 36 | 37 | public enum UpdateState 38 | { 39 | CheckingUpdate, 40 | CheckFailed, 41 | UpToDate, 42 | ReadyToDownload, 43 | ErrorDownloading, 44 | ReadyToInstall 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /WSATools/WSATools/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Principal; 2 | using System.Windows; 3 | 4 | namespace WSATools 5 | { 6 | /// 7 | /// Interaction logic for App.xaml 8 | /// 9 | public partial class App : Application 10 | { 11 | public App() 12 | { 13 | /** 14 | * 当前用户是管理员的时候,直接启动应用程序 15 | * 如果不是管理员,则使用启动对象启动程序,以确保使用管理员身份运行 16 | */ 17 | //获得当前登录的Windows用户标示 18 | WindowsIdentity identity = WindowsIdentity.GetCurrent(); 19 | WindowsPrincipal principal = new WindowsPrincipal(identity); 20 | //判断当前登录用户是否为管理员 21 | //if (!principal.IsInRole(WindowsBuiltInRole.Administrator)) 22 | //{ 23 | // //创建启动对象 24 | // System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); 25 | // startInfo.UseShellExecute = true; 26 | // startInfo.WorkingDirectory = Environment.CurrentDirectory; 27 | // startInfo.FileName = Assembly.GetExecutingAssembly().Location; 28 | // //设置启动动作,确保以管理员身份运行 29 | // startInfo.Verb = "runas"; 30 | // try 31 | // { 32 | // System.Diagnostics.Process.Start(startInfo); 33 | // } 34 | // catch 35 | // { 36 | // return; 37 | // } 38 | // //退出 39 | // Application.Current.Shutdown(); 40 | //} 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /WSATools/WSATools/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WSATools.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.1.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("2021-11-12")] 29 | public global::System.DateTime UpdateDate { 30 | get { 31 | return ((global::System.DateTime)(this["UpdateDate"])); 32 | } 33 | set { 34 | this["UpdateDate"] = value; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /WSATools/WSATools/Styles/SettingButton.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 21 | 22 | 23 | 33 | -------------------------------------------------------------------------------- /WSATools/WSATools/Styles/SettingsGroup.xaml: -------------------------------------------------------------------------------- 1 | 6 | 37 | -------------------------------------------------------------------------------- /WSATools/WSATools.Core/Receivers/StorageReceiver.cs: -------------------------------------------------------------------------------- 1 | using AdvancedSharpAdbClient; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections.ObjectModel; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | using System.Threading.Tasks; 9 | using WSATools.Core.Models; 10 | 11 | namespace WSATools.Core.Receivers 12 | { 13 | public class StorageReceiver : MultiLineReceiver 14 | { 15 | public StorageReceiver() 16 | { 17 | Storages = new ObservableCollection(); 18 | } 19 | 20 | public ObservableCollection Storages { get; private set; } 21 | 22 | /// 23 | /// Processes the new lines. 24 | /// 25 | /// The lines. 26 | protected override void ProcessNewLines(IEnumerable lines) 27 | { 28 | Storages.Clear(); 29 | 30 | foreach (string line in lines) 31 | { 32 | if (!string.IsNullOrEmpty(line) && !line.StartsWith("Filesystem")) 33 | { 34 | string[] parts = Regex.Split(line, "\\s+", RegexOptions.IgnoreCase); 35 | StorageInfo Info = new StorageInfo() 36 | { 37 | Mountedon = parts[5].Trim(), 38 | Filesystem = parts[0].Trim(), 39 | Size = Convert.ToInt32(parts[1].Trim()), 40 | Used = Convert.ToInt32(parts[2].Trim()), 41 | Available = Convert.ToInt32(parts[3].Trim()), 42 | Use = Convert.ToInt32(parts[4].Trim().Replace("%", string.Empty)) 43 | }; 44 | Storages.Add(Info); 45 | } 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | APK Installer LOGO 2 | 3 | # WSA Tools 4 | 一个基于 Modern WPF 的 WSA 工具箱 5 | 6 | GitHub 7 | GitHub 8 | GitHub 9 | 10 | GitHub All Releases 11 | Baidu Netdisk 12 | 13 | ## 目录 14 | - [WSA Tools](#wsa-tools) 15 | - [目录](#目录) 16 | - [如何安装应用](#如何安装应用) 17 | - [最低需求](#最低需求) 18 | - [使用到的模块](#使用到的模块) 19 | - [鸣谢](#鸣谢) 20 | - [Star 数量统计](#star-数量统计) 21 | 22 | ## 如何安装应用 23 | ### 最低需求 24 | - Windows 7 Build 7231 及以上 25 | - 设备需支持ARM/ARM64/x86/x64 26 | - 至少20MB的空余储存空间(用于储存安装包与安装应用) 27 | 28 | ## 使用到的模块 29 | - [FluentWPF](https://github.com/sourcechord/FluentWPF "FluentWPF") 30 | - [ModernWpf](https://github.com/Kinnara/ModernWpf "ModernWpf") 31 | - [Windows Community Toolkit](https://github.com/CommunityToolkit/WindowsCommunityToolkit "Windows Community Toolkit") 32 | 33 | ## 鸣谢 34 | - 所有为 WSA Tools 做出贡献的同志们 35 | - **铺路尚未成功,同志仍需努力!** 36 | 37 | ## Star 数量统计 38 | [![Star 数量统计](https://starchart.cc/Paving-Base/WSA-Tools.svg)](https://starchart.cc/Paving-Base/WSA-Tools "Star 数量统计") -------------------------------------------------------------------------------- /.github/workflows/build-and-publish.yml: -------------------------------------------------------------------------------- 1 | name: build and publish 2 | 3 | on: 4 | push: 5 | pull_request: 6 | branches: [main] 7 | paths: 8 | - 'WSATools/**' 9 | 10 | jobs: 11 | build-and-test: 12 | 13 | name: build-and-publish 14 | runs-on: windows-latest 15 | 16 | env: 17 | Solution_Name: WSATools/WSATools/WSATools.csproj 18 | Project_Directory: WSATools/WSATools 19 | 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v3 23 | with: 24 | fetch-depth: 0 25 | 26 | - name: Clone ModernWpf 27 | run: | 28 | echo 'Cloning into sources folder at: ..\ModernWpf' 29 | git clone https://github.com/wherewhere/ModernWpf.git --progress --branch master --single-branch --depth=1 ..\ModernWpf 30 | exit 31 | 32 | - name: Clone APPXManager 33 | run: | 34 | echo 'Cloning into sources folder at: ..\APPX-Manager' 35 | git clone https://github.com/wherewhere/APPX-Manager.git --progress --branch master --single-branch --depth=1 ..\APPX-Manager 36 | exit 37 | 38 | - name: Clone SharpAdbClient 39 | run: | 40 | echo 'Cloning into sources folder at: ..\AdvancedSharpAdbClient' 41 | git clone https://github.com/yungd1plomat/AdvancedSharpAdbClient.git --progress --branch main --single-branch --depth=1 ..\AdvancedSharpAdbClient 42 | exit 43 | 44 | # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild 45 | - name: Setup MSBuild.exe 46 | uses: microsoft/setup-msbuild@v1 47 | with: 48 | msbuild-architecture: x64 49 | 50 | # Restore the application to populate the obj folder with RuntimeIdentifiers 51 | - name: Restore the application 52 | run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration 53 | env: 54 | Configuration: Release 55 | 56 | # Create the app package by building and packaging the Windows Application Packaging project 57 | - name: Publish the app package 58 | run: msbuild $env:Solution_Name /p:Configuration=$env:Configuration /p:Platform=$env:Platforms 59 | env: 60 | Platforms: "Any CPU" 61 | Configuration: Release 62 | 63 | # Upload the MSIX package: https://github.com/marketplace/actions/upload-a-build-artifact 64 | - name: Upload build artifacts 65 | uses: actions/upload-artifact@v3 66 | with: 67 | name: Publish Package 68 | path: WSATools/WSATools/bin/** 69 | -------------------------------------------------------------------------------- /WSATools/WSATools.Package/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | 15 | WSA Tools 16 | wherewhere 17 | Images\StoreLogo.png 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /WSATools/WSATools/Models/SystemVersionInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace WSATools.Models 4 | { 5 | public readonly struct SystemVersionInfo 6 | { 7 | public SystemVersionInfo(int major, int minor, int build, int revision = 0) 8 | { 9 | Major = major; 10 | Minor = minor; 11 | Build = build; 12 | Revision = revision; 13 | } 14 | 15 | public int Major { get; } 16 | 17 | public int Minor { get; } 18 | 19 | public int Build { get; } 20 | 21 | public int Revision { get; } 22 | 23 | public bool Equals(SystemVersionInfo other) => Major == other.Major && Minor == other.Minor && Build == other.Build && Revision == other.Revision; 24 | 25 | public override bool Equals(object obj) => obj is SystemVersionInfo other && Equals(other); 26 | 27 | public override int GetHashCode() => Major.GetHashCode() ^ Minor.GetHashCode() ^ Build.GetHashCode() ^ Revision.GetHashCode(); 28 | 29 | public static bool operator ==(SystemVersionInfo left, SystemVersionInfo right) => left.Equals(right); 30 | 31 | public static bool operator !=(SystemVersionInfo left, SystemVersionInfo right) => !(left == right); 32 | 33 | public int CompareTo(SystemVersionInfo other) 34 | { 35 | if (Major != other.Major) 36 | { 37 | return Major.CompareTo(other.Major); 38 | } 39 | 40 | if (Minor != other.Minor) 41 | { 42 | return Minor.CompareTo(other.Minor); 43 | } 44 | 45 | if (Build != other.Build) 46 | { 47 | return Build.CompareTo(other.Build); 48 | } 49 | 50 | if (Revision != other.Revision) 51 | { 52 | return Revision.CompareTo(other.Revision); 53 | } 54 | 55 | return 0; 56 | } 57 | 58 | public int CompareTo(object obj) 59 | { 60 | if (!(obj is SystemVersionInfo other)) 61 | { 62 | throw new ArgumentException(); 63 | } 64 | 65 | return CompareTo(other); 66 | } 67 | 68 | public static bool operator <(SystemVersionInfo left, SystemVersionInfo right) => left.CompareTo(right) < 0; 69 | 70 | public static bool operator <=(SystemVersionInfo left, SystemVersionInfo right) => left.CompareTo(right) <= 0; 71 | 72 | public static bool operator >(SystemVersionInfo left, SystemVersionInfo right) => left.CompareTo(right) > 0; 73 | 74 | public static bool operator >=(SystemVersionInfo left, SystemVersionInfo right) => left.CompareTo(right) >= 0; 75 | 76 | public override string ToString() => $"{Major}.{Minor}.{Build}.{Revision}"; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /WSATools/WSATools/Pages/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 29 | 35 | 36 | 46 | 47 | 51 | 55 | 56 | 57 | 58 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /WSATools/WSATools/App.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 641 41 | 42 | 0 43 | -4,0,12,0 44 | 45 | 46 | 0,48,0,0 47 | 1,1,0,0 48 | 8,0,0,0 49 | 56,34,0,0 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /WSATools/WSATools/Controls/SettingsGroup.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Windows; 3 | using System.Windows.Automation.Peers; 4 | using System.Windows.Controls; 5 | 6 | namespace WSATools.Controls 7 | { 8 | /// 9 | /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。 10 | /// 11 | /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。 12 | /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 13 | /// 元素中: 14 | /// 15 | /// xmlns:MyNamespace="clr-namespace:WSATools.Controls" 16 | /// 17 | /// 18 | /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。 19 | /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 20 | /// 元素中: 21 | /// 22 | /// xmlns:MyNamespace="clr-namespace:WSATools.Controls;assembly=WSATools.Controls" 23 | /// 24 | /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用, 25 | /// 并重新生成以避免编译错误: 26 | /// 27 | /// 在解决方案资源管理器中右击目标项目,然后依次单击 28 | /// “添加引用”->“项目”->[浏览查找并选择此项目] 29 | /// 30 | /// 31 | /// 步骤 2) 32 | /// 继续操作并在 XAML 文件中使用控件。 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// Represents a control that can contain multiple settings (or other) controls 39 | /// 40 | [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")] 41 | [TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")] 42 | public partial class SettingsGroup : ItemsControl 43 | { 44 | public SettingsGroup() 45 | { 46 | DefaultStyleKey = typeof(SettingsGroup); 47 | } 48 | 49 | public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register( 50 | "Header", 51 | typeof(string), 52 | typeof(SettingsGroup), 53 | new PropertyMetadata(default(string))); 54 | 55 | [Localizable(true)] 56 | public string Header 57 | { 58 | get => (string)GetValue(HeaderProperty); 59 | set => SetValue(HeaderProperty, value); 60 | } 61 | 62 | public override void OnApplyTemplate() 63 | { 64 | IsEnabledChanged -= SettingsGroup_IsEnabledChanged; 65 | SetEnabledState(); 66 | IsEnabledChanged += SettingsGroup_IsEnabledChanged; 67 | base.OnApplyTemplate(); 68 | } 69 | 70 | private void SettingsGroup_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) 71 | { 72 | SetEnabledState(); 73 | } 74 | 75 | private void SetEnabledState() 76 | { 77 | VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true); 78 | } 79 | 80 | protected override AutomationPeer OnCreateAutomationPeer() 81 | { 82 | return new SettingsGroupAutomationPeer(this); 83 | } 84 | } 85 | 86 | public class SettingsGroupAutomationPeer : FrameworkElementAutomationPeer 87 | { 88 | public SettingsGroupAutomationPeer(SettingsGroup owner) 89 | : base(owner) 90 | { 91 | } 92 | 93 | protected override string GetNameCore() 94 | { 95 | SettingsGroup selectedSettingsGroup = (SettingsGroup)Owner; 96 | return selectedSettingsGroup.Header; 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /WSATools/WSATools/WSATools.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | True 5 | favicon.ico 6 | wherewhere 7 | Copyright © 2017 - 2021 Paving Base. All Rights Reserved 8 | 一个基于 Modern WPF 的 WSA 管理工具 9 | preview 10 | WinExe 11 | https://github.com/Paving-Base/WSA-Tools 12 | https://github.com/Paving-Base/WSA-Tools 13 | net4.8 14 | true 15 | 0.0.1 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | True 25 | \ 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | runtime; build; native; contentfiles; analyzers; buildtransitive 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | True 53 | True 54 | Settings.settings 55 | 56 | 57 | 58 | 59 | 60 | SettingsSingleFileGenerator 61 | Settings.Designer.cs 62 | 63 | 64 | 65 | 66 | 67 | $(DefaultXamlRuntime) 68 | Designer 69 | 70 | 71 | $(DefaultXamlRuntime) 72 | Designer 73 | 74 | 75 | $(DefaultXamlRuntime) 76 | Designer 77 | 78 | 79 | $(DefaultXamlRuntime) 80 | Designer 81 | 82 | 83 | $(DefaultXamlRuntime) 84 | Designer 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /WSATools/WSATools/Helpers/Converter/IsEqualToObjectConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace WSATools.Helpers.Converter 7 | { 8 | public partial class IsEqualToObjectConverter : DependencyObject, IValueConverter 9 | { 10 | /// 11 | /// Identifies the property. 12 | /// 13 | public static readonly DependencyProperty TrueValueProperty = 14 | DependencyProperty.Register(nameof(TrueValue), typeof(object), typeof(IsEqualToObjectConverter), new PropertyMetadata(null)); 15 | 16 | /// 17 | /// Identifies the property. 18 | /// 19 | public static readonly DependencyProperty FalseValueProperty = 20 | DependencyProperty.Register(nameof(FalseValue), typeof(object), typeof(IsEqualToObjectConverter), new PropertyMetadata(null)); 21 | 22 | /// 23 | /// Gets or sets the value to be returned when the boolean is true 24 | /// 25 | public object TrueValue 26 | { 27 | get { return GetValue(TrueValueProperty); } 28 | set { SetValue(TrueValueProperty, value); } 29 | } 30 | 31 | /// 32 | /// Gets or sets the value to be returned when the boolean is false 33 | /// 34 | public object FalseValue 35 | { 36 | get { return GetValue(FalseValueProperty); } 37 | set { SetValue(FalseValueProperty, value); } 38 | } 39 | 40 | /// 41 | /// Convert a boolean value to an other object. 42 | /// 43 | /// The source data being passed to the target. 44 | /// The type of the target property, as a type reference. 45 | /// An optional parameter to be used to invert the converter logic. 46 | /// The language of the conversion. 47 | /// The value to be passed to the target dependency property. 48 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 49 | { 50 | bool boolValue = value.ToString() == (string)parameter; 51 | 52 | return ConverterTools.Convert(boolValue ? TrueValue : FalseValue, targetType); 53 | } 54 | 55 | /// 56 | /// Convert back the value to a boolean 57 | /// 58 | /// If the parameter is a reference type, must match its reference to return true. 59 | /// The target data being passed to the source. 60 | /// The type of the target property, as a type reference (System.Type for Microsoft .NET, a TypeName helper struct for Visual C++ component extensions (C++/CX)). 61 | /// An optional parameter to be used to invert the converter logic. 62 | /// The language of the conversion. 63 | /// The value to be passed to the source object. 64 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 65 | { 66 | return value; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /WSATools/WSATools/ViewModels/HomeViewModel.cs: -------------------------------------------------------------------------------- 1 | using APPXManager.Models; 2 | using System.Collections.ObjectModel; 3 | using System.ComponentModel; 4 | using System.Threading.Tasks; 5 | using WSATools.Core.Helpers; 6 | using WSATools.Core.Models; 7 | using WSATools.Helpers; 8 | 9 | namespace WSATools.ViewModels 10 | { 11 | public sealed class HomeViewModel : INotifyPropertyChanged 12 | { 13 | private PackageInfo _WSAInfo = new PackageInfo(); 14 | public PackageInfo WSAInfo 15 | { 16 | get => _WSAInfo; 17 | set 18 | { 19 | if (_WSAInfo != value) 20 | { 21 | _WSAInfo = value; 22 | RaisePropertyChangedEvent(); 23 | } 24 | } 25 | } 26 | 27 | private bool _isWSAStart = WSAHelper.IsWSARunning; 28 | public bool IsWSAStart 29 | { 30 | get => _isWSAStart; 31 | set 32 | { 33 | if (_isWSAStart != value) 34 | { 35 | _isWSAStart = value; 36 | RaisePropertyChangedEvent(); 37 | } 38 | } 39 | } 40 | 41 | private bool _isWSAInstalled = false; 42 | public bool IsWSAInstalled 43 | { 44 | get => _isWSAInstalled; 45 | set 46 | { 47 | if (_isWSAInstalled != value) 48 | { 49 | _isWSAInstalled = value; 50 | RaisePropertyChangedEvent(); 51 | } 52 | } 53 | } 54 | 55 | private double _storageUsage; 56 | public double StorageUsage 57 | { 58 | get => _storageUsage; 59 | set 60 | { 61 | if (_storageUsage != value) 62 | { 63 | _storageUsage = value; 64 | RaisePropertyChangedEvent(); 65 | } 66 | } 67 | } 68 | 69 | private string _storageUsageText; 70 | public string StorageUsageText 71 | { 72 | get => _storageUsageText; 73 | set 74 | { 75 | if (_storageUsageText != value) 76 | { 77 | _storageUsageText = value; 78 | RaisePropertyChangedEvent(); 79 | } 80 | } 81 | } 82 | 83 | public event PropertyChangedEventHandler PropertyChanged; 84 | 85 | private void RaisePropertyChangedEvent([System.Runtime.CompilerServices.CallerMemberName] string name = null) 86 | { 87 | if (name != null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } 88 | } 89 | 90 | public HomeViewModel() 91 | { 92 | //(IsWSAInstalled, WSAInfo) = WSAHelper.GetWSAInfo(); 93 | //ADBHelper.InitilizeADB(); 94 | //ADBHelper.ConnectWSA(); 95 | } 96 | 97 | public void Refresh() 98 | { 99 | ObservableCollection storages = ADBHelper.GetStorageInfo(); 100 | int Size = 0, Used = 0, Available = 0; 101 | foreach (StorageInfo storage in storages) 102 | { 103 | Size += storage.Size; 104 | Used += storage.Used; 105 | Available += storage.Available; 106 | } 107 | StorageUsage = (double)Used / Size; 108 | StorageUsageText = $"一共 {((double)Size * 1024).GetSizeString()} 空余 {((double)Available * 1024).GetSizeString()}"; 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /WSATools/WSATools/Controls/PageHeader.xaml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 23 | 24 | 28 | 29 | 30 | 31 | 32 | 36 | 40 | 49 | 50 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 69 | 75 | 76 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /WSATools/WSATools/Helpers/Converter/BoolToObjectConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace WSATools.Helpers.Converter 7 | { 8 | /// 9 | /// This class converts a boolean value into an other object. 10 | /// Can be used to convert true/false to visibility, a couple of colors, couple of images, etc. 11 | /// 12 | public partial class BoolToObjectConverter : DependencyObject, IValueConverter 13 | { 14 | /// 15 | /// Identifies the property. 16 | /// 17 | public static readonly DependencyProperty TrueValueProperty = 18 | DependencyProperty.Register(nameof(TrueValue), typeof(object), typeof(BoolToObjectConverter), new PropertyMetadata(null)); 19 | 20 | /// 21 | /// Identifies the property. 22 | /// 23 | public static readonly DependencyProperty FalseValueProperty = 24 | DependencyProperty.Register(nameof(FalseValue), typeof(object), typeof(BoolToObjectConverter), new PropertyMetadata(null)); 25 | 26 | /// 27 | /// Gets or sets the value to be returned when the boolean is true 28 | /// 29 | public object TrueValue 30 | { 31 | get { return GetValue(TrueValueProperty); } 32 | set { SetValue(TrueValueProperty, value); } 33 | } 34 | 35 | /// 36 | /// Gets or sets the value to be returned when the boolean is false 37 | /// 38 | public object FalseValue 39 | { 40 | get { return GetValue(FalseValueProperty); } 41 | set { SetValue(FalseValueProperty, value); } 42 | } 43 | 44 | /// 45 | /// Convert a boolean value to an other object. 46 | /// 47 | /// The source data being passed to the target. 48 | /// The type of the target property, as a type reference. 49 | /// An optional parameter to be used to invert the converter logic. 50 | /// The language of the conversion. 51 | /// The value to be passed to the target dependency property. 52 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 53 | { 54 | bool boolValue = value is bool && (bool)value; 55 | 56 | // Negate if needed 57 | if (ConverterTools.TryParseBool(parameter)) 58 | { 59 | boolValue = !boolValue; 60 | } 61 | 62 | return ConverterTools.Convert(boolValue ? TrueValue : FalseValue, targetType); 63 | } 64 | 65 | /// 66 | /// Convert back the value to a boolean 67 | /// 68 | /// If the parameter is a reference type, must match its reference to return true. 69 | /// The target data being passed to the source. 70 | /// The type of the target property, as a type reference (System.Type for Microsoft .NET, a TypeName helper struct for Visual C++ component extensions (C++/CX)). 71 | /// An optional parameter to be used to invert the converter logic. 72 | /// The language of the conversion. 73 | /// The value to be passed to the source object. 74 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 75 | { 76 | bool result = Equals(value, ConverterTools.Convert(TrueValue, value.GetType())); 77 | 78 | if (ConverterTools.TryParseBool(parameter)) 79 | { 80 | result = !result; 81 | } 82 | 83 | return result; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /WSATools/WSATools/Controls/PageHeader.xaml.cs: -------------------------------------------------------------------------------- 1 | using ModernWpf.Media.Animation; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | using System.Windows.Media.Animation; 5 | 6 | namespace WSATools.Controls 7 | { 8 | /// 9 | /// PageHeader.xaml 的交互逻辑 10 | /// 11 | public partial class PageHeader : UserControl 12 | { 13 | public object Title 14 | { 15 | get { return GetValue(TitleProperty); } 16 | set { SetValue(TitleProperty, value); } 17 | } 18 | 19 | public static readonly DependencyProperty TitleProperty = 20 | DependencyProperty.Register("Title", typeof(object), typeof(PageHeader), new PropertyMetadata(null)); 21 | 22 | 23 | public Thickness HeaderPadding 24 | { 25 | get { return (Thickness)GetValue(HeaderPaddingProperty); } 26 | set { SetValue(HeaderPaddingProperty, value); } 27 | } 28 | 29 | // Using a DependencyProperty as the backing store for BackgroundColorOpacity. This enables animation, styling, binding, etc... 30 | public static readonly DependencyProperty HeaderPaddingProperty = 31 | DependencyProperty.Register("HeaderPadding", typeof(Thickness), typeof(PageHeader), new PropertyMetadata((Thickness)App.Current.Resources["PageHeaderDefaultPadding"])); 32 | 33 | 34 | public double BackgroundColorOpacity 35 | { 36 | get { return (double)GetValue(BackgroundColorOpacityProperty); } 37 | set { SetValue(BackgroundColorOpacityProperty, value); } 38 | } 39 | 40 | // Using a DependencyProperty as the backing store for BackgroundColorOpacity. This enables animation, styling, binding, etc... 41 | public static readonly DependencyProperty BackgroundColorOpacityProperty = 42 | DependencyProperty.Register("BackgroundColorOpacity", typeof(double), typeof(PageHeader), new PropertyMetadata(0.0)); 43 | 44 | 45 | public double AcrylicOpacity 46 | { 47 | get { return (double)GetValue(AcrylicOpacityProperty); } 48 | set { SetValue(AcrylicOpacityProperty, value); } 49 | } 50 | 51 | // Using a DependencyProperty as the backing store for BackgroundColorOpacity. This enables animation, styling, binding, etc... 52 | public static readonly DependencyProperty AcrylicOpacityProperty = 53 | DependencyProperty.Register("AcrylicOpacity", typeof(double), typeof(PageHeader), new PropertyMetadata(0.3)); 54 | 55 | public double ShadowOpacity 56 | { 57 | get { return (double)GetValue(ShadowOpacityProperty); } 58 | set { SetValue(ShadowOpacityProperty, value); } 59 | } 60 | 61 | // Using a DependencyProperty as the backing store for BackgroundColorOpacity. This enables animation, styling, binding, etc... 62 | public static readonly DependencyProperty ShadowOpacityProperty = 63 | DependencyProperty.Register("ShadowOpacity", typeof(double), typeof(PageHeader), new PropertyMetadata(0.0)); 64 | 65 | public UIElement TitlePanel 66 | { 67 | get { return PageTitle; } 68 | } 69 | 70 | public PageHeader() 71 | { 72 | this.InitializeComponent(); 73 | } 74 | 75 | /// 76 | /// This method will be called when a gets unloaded. 77 | /// Put any code in here that should be done when a gets unloaded. 78 | /// 79 | /// The sender (the ItemPage) 80 | /// The of the ItemPage that was unloaded. 81 | public void Event_ItemPage_Unloaded(object sender, RoutedEventArgs e) 82 | { 83 | 84 | } 85 | 86 | public void RectanglePointerEntered() 87 | { 88 | var storyboard = new Storyboard(); 89 | var animation = new FadeInThemeAnimation { TargetName = nameof(MessageBar) }; 90 | storyboard.Children.Add(animation); 91 | storyboard.Begin(); 92 | } 93 | 94 | public void RectanglePointerExited() 95 | { 96 | var storyboard = new Storyboard(); 97 | var animation = new FadeOutThemeAnimation { TargetName = nameof(MessageBar) }; 98 | storyboard.Children.Add(animation); 99 | storyboard.Begin(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /WSATools/WSATools/ViewModels/SettingsViewModel.cs: -------------------------------------------------------------------------------- 1 | using APKInstaller.Helpers; 2 | using CommunityToolkit.Mvvm.Input; 3 | using System; 4 | using System.ComponentModel; 5 | using System.Reflection; 6 | using System.Threading.Tasks; 7 | using Windows.System; 8 | using WSATools.Helpers; 9 | using WSATools.Models; 10 | using WSATools.Pages.SettingsPages; 11 | using WSATools.Properties; 12 | 13 | namespace WSATools.ViewModels 14 | { 15 | public sealed class SettingsViewModel : INotifyPropertyChanged 16 | { 17 | public IRelayCommand GotoUpdateCommand { get; } 18 | public IRelayCommand GotoTestPageCommand { get; } 19 | public IAsyncRelayCommand CheackUpdateCommand { get; } 20 | 21 | private DateTime _updateDate = Settings.Default.UpdateDate; 22 | public DateTime UpdateDate 23 | { 24 | get => _updateDate; 25 | set 26 | { 27 | if (_updateDate != value) 28 | { 29 | Settings.Default.UpdateDate = value; 30 | Settings.Default.Save(); 31 | _updateDate = Settings.Default.UpdateDate; 32 | RaisePropertyChangedEvent(); 33 | } 34 | } 35 | } 36 | 37 | private UpdateInfo _updateInfo = new UpdateInfo(); 38 | public UpdateInfo UpdateInfo 39 | { 40 | get => _updateInfo; 41 | set 42 | { 43 | if (_updateInfo != value) 44 | { 45 | _updateInfo = value; 46 | RaisePropertyChangedEvent(); 47 | } 48 | } 49 | } 50 | 51 | private string _updateErrorMessage = string.Empty; 52 | public string UpdateErrorMessage 53 | { 54 | get => _updateErrorMessage; 55 | set 56 | { 57 | if (_updateErrorMessage != value) 58 | { 59 | _updateErrorMessage = value; 60 | RaisePropertyChangedEvent(); 61 | } 62 | } 63 | } 64 | 65 | private bool _checkingUpdate = false; 66 | public bool CheckingUpdate 67 | { 68 | get => _checkingUpdate; 69 | set 70 | { 71 | if (_checkingUpdate != value) 72 | { 73 | _checkingUpdate = value; 74 | RaisePropertyChangedEvent(); 75 | } 76 | } 77 | } 78 | 79 | public string VersionText 80 | { 81 | get 82 | { 83 | string ver = $"{Assembly.GetExecutingAssembly().GetName().Version.Build}.{Assembly.GetExecutingAssembly().GetName().Version.Major}.{Assembly.GetExecutingAssembly().GetName().Version.Minor}"; 84 | string name = "WSA Tools"; 85 | return $"{name} v{ver}"; 86 | } 87 | } 88 | 89 | public event PropertyChangedEventHandler PropertyChanged; 90 | 91 | private void RaisePropertyChangedEvent([System.Runtime.CompilerServices.CallerMemberName] string name = null) 92 | { 93 | if (name != null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } 94 | } 95 | 96 | public SettingsViewModel() 97 | { 98 | GotoUpdateCommand = new RelayCommand(GotoUpdate); 99 | GotoTestPageCommand = new RelayCommand(GotoTestPage); 100 | CheackUpdateCommand = new AsyncRelayCommand(CheckUpdate); 101 | if (UpdateDate == DateTime.MinValue) { _ = CheckUpdate(); } 102 | } 103 | 104 | private async Task CheckUpdate() 105 | { 106 | CheckingUpdate = true; 107 | try 108 | { 109 | UpdateInfo = await UpdateHelper.CheckUpdateAsync("Paving-Base", "WSA-Tools"); 110 | } 111 | catch (Exception ex) 112 | { 113 | UpdateErrorMessage = ex.Message; 114 | UpdateInfo = new UpdateInfo() 115 | { 116 | UpdateState = UpdateState.CheckFailed 117 | }; 118 | } 119 | UpdateDate = DateTime.Now; 120 | CheckingUpdate = false; 121 | } 122 | 123 | private void GotoTestPage() => UIHelper.Navigate(typeof(TestPage)); 124 | 125 | private void GotoUpdate() => _ = Launcher.LaunchUriAsync(new Uri(UpdateInfo.ReleaseUrl)); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /WSATools/WSATools/Helpers/UpdateHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Net; 4 | using System.Net.Http; 5 | using System.Reflection; 6 | using System.Text.Json; 7 | using System.Threading.Tasks; 8 | using WSATools.Models; 9 | 10 | namespace APKInstaller.Helpers 11 | { 12 | public static class UpdateHelper 13 | { 14 | private const string KKPP_API = "https://v2.kkpp.cc/repos/{0}/{1}/releases/latest"; 15 | private const string GITHUB_API = "https://api.github.com/repos/{0}/{1}/releases/latest"; 16 | 17 | public static async Task CheckUpdateAsync(string username, string repository, Version currentVersion = null) 18 | { 19 | UpdateInfo Info = new UpdateInfo() 20 | { 21 | UpdateState = UpdateState.CheckingUpdate 22 | }; 23 | 24 | if (string.IsNullOrEmpty(username)) 25 | { 26 | throw new ArgumentNullException(nameof(username)); 27 | } 28 | 29 | if (string.IsNullOrEmpty(repository)) 30 | { 31 | throw new ArgumentNullException(nameof(repository)); 32 | } 33 | 34 | ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; 35 | HttpClient client = new HttpClient(); 36 | client.DefaultRequestHeaders.Add("User-Agent", username); 37 | string url = string.Format(GITHUB_API, username, repository); 38 | HttpResponseMessage response = await client.GetAsync(url); 39 | if (!response.IsSuccessStatusCode) 40 | { 41 | url = string.Format(KKPP_API, username, repository); 42 | response = await client.GetAsync(url); 43 | } 44 | string responseBody = await response.Content.ReadAsStringAsync(); 45 | UpdateInfo result = JsonSerializer.Deserialize(responseBody); 46 | 47 | if (result != null) 48 | { 49 | if (currentVersion == null) 50 | { 51 | currentVersion = Assembly.GetEntryAssembly().GetName().Version; 52 | } 53 | 54 | SystemVersionInfo newVersionInfo = GetAsVersionInfo(result.TagName); 55 | int major = currentVersion.Major == -1 ? 0 : currentVersion.Major; 56 | int minor = currentVersion.Minor == -1 ? 0 : currentVersion.Minor; 57 | int build = currentVersion.Build == -1 ? 0 : currentVersion.Build; 58 | int revision = currentVersion.Revision == -1 ? 0 : currentVersion.Revision; 59 | 60 | SystemVersionInfo currentVersionInfo = new SystemVersionInfo(major, minor, build, revision); 61 | 62 | Info.Changelog = result?.Changelog; 63 | Info.CreatedAt = Convert.ToDateTime(result?.CreatedAt); 64 | Info.Assets = result.Assets; 65 | Info.IsPreRelease = result.IsPreRelease; 66 | Info.PublishedAt = Convert.ToDateTime(result?.PublishedAt); 67 | Info.TagName = result.TagName; 68 | Info.ApiUrl = result?.ApiUrl; 69 | Info.ReleaseUrl = result?.ReleaseUrl; 70 | Info.IsExistNewVersion = newVersionInfo > currentVersionInfo; 71 | Info.UpdateState = Info.IsExistNewVersion ? UpdateState.ReadyToDownload : UpdateState.UpToDate; 72 | } 73 | else 74 | { 75 | Info.UpdateState = UpdateState.UpToDate; 76 | } 77 | return Info; 78 | } 79 | 80 | private static SystemVersionInfo GetAsVersionInfo(string version) 81 | { 82 | System.Collections.Generic.List nums = GetVersionNumbers(version).Split('.').Select(int.Parse).ToList(); 83 | 84 | if (nums.Count <= 1) 85 | { 86 | return new SystemVersionInfo(nums[0], 0, 0, 0); 87 | } 88 | else if (nums.Count <= 2) 89 | { 90 | return new SystemVersionInfo(nums[0], nums[1], 0, 0); 91 | } 92 | else if (nums.Count <= 3) 93 | { 94 | return new SystemVersionInfo(nums[0], nums[1], nums[2], 0); 95 | } 96 | else 97 | { 98 | return new SystemVersionInfo(nums[0], nums[1], nums[2], nums[3]); 99 | } 100 | } 101 | 102 | private static string GetVersionNumbers(string version) 103 | { 104 | string allowedChars = "01234567890."; 105 | return new string(version.Where(c => allowedChars.Contains(c)).ToArray()); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /WSATools/WSATools.Core/Helpers/ADBHelper.cs: -------------------------------------------------------------------------------- 1 | using AdvancedSharpAdbClient; 2 | using AdvancedSharpAdbClient.DeviceCommands; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using System.Diagnostics; 7 | using System.Linq; 8 | using System.Net; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using WSATools.Core.Models; 12 | using WSATools.Core.Receivers; 13 | 14 | namespace WSATools.Core.Helpers 15 | { 16 | public static class ADBHelper 17 | { 18 | private static IEnumerable DeviceList; 19 | 20 | public static DeviceData WSA; 21 | public static bool IsConnectWSA = false; 22 | public static StartServerResult? ADBStatus; 23 | public static AdvancedAdbClient ADBClient = new AdvancedAdbClient(); 24 | public static DeviceMonitor Monitor = new DeviceMonitor(new AdbSocket(new IPEndPoint(IPAddress.Loopback, AdvancedAdbClient.AdbServerPort))); 25 | 26 | public static void InitilizeADB() => InitilizeADB(null); 27 | public static void InitilizeADB(IProgress progress) 28 | { 29 | Process[] processes = Process.GetProcessesByName("adb"); 30 | if (processes != null && processes.Any()) 31 | { 32 | ADBStatus = new AdbServer().StartServer(processes.First().MainModule.FileName, restartServerIfNewer: false); 33 | } 34 | if (progress != null) 35 | { 36 | progress.Report(50); 37 | } 38 | if (ADBStatus != null) 39 | { 40 | Monitor.DeviceChanged += OnDeviceChanged; 41 | DeviceList = new AdvancedAdbClient().GetDevices(); 42 | } 43 | if (progress != null) 44 | { 45 | progress.Report(100); 46 | } 47 | } 48 | 49 | public static void ConnectWSA() => ConnectWSA(null); 50 | public static void ConnectWSA(IProgress progress) 51 | { 52 | if (DeviceList != null && DeviceList.Any()) 53 | { 54 | ConsoleOutputReceiver receiver = new ConsoleOutputReceiver(); 55 | foreach (DeviceData device in DeviceList) 56 | { 57 | if (progress != null) 58 | { 59 | progress.Report((double)(DeviceList.ToList().IndexOf(device) + 1) * 100 / DeviceList.Count()); 60 | } 61 | if (device == null || device.State == DeviceState.Offline) { continue; } 62 | ADBClient.ExecuteRemoteCommand("getprop ro.boot.hardware", device, receiver); 63 | if (receiver.ToString().Contains("windows")) 64 | { 65 | WSA = device ?? WSA; 66 | IsConnectWSA = true; 67 | break; 68 | } 69 | } 70 | } 71 | else 72 | { 73 | IsConnectWSA = false; 74 | } 75 | } 76 | 77 | public static ObservableCollection GetAppsList() 78 | { 79 | ObservableCollection Applications = new ObservableCollection(); 80 | AdvancedAdbClient client = new AdvancedAdbClient(); 81 | PackageManager manager = new PackageManager(client, WSA); 82 | foreach (KeyValuePair app in manager.Packages) 83 | { 84 | if (!string.IsNullOrEmpty(app.Key)) 85 | { 86 | ConsoleOutputReceiver receiver = new ConsoleOutputReceiver(); 87 | client.ExecuteRemoteCommand($"pidof {app.Key}", WSA, receiver); 88 | bool isactive = !string.IsNullOrEmpty(receiver.ToString()); 89 | Applications.Add(new APKInfo() 90 | { 91 | Name = app.Key, 92 | IsActive = isactive, 93 | VersionInfo = manager.GetVersionInfo(app.Key) 94 | }); 95 | } 96 | } 97 | return Applications; 98 | } 99 | 100 | public static ObservableCollection GetStorageInfo() 101 | { 102 | StorageReceiver receiver = new StorageReceiver(); 103 | if (WSA != null) 104 | { 105 | ADBClient.ExecuteRemoteCommand("df", WSA, receiver); 106 | } 107 | return receiver.Storages; 108 | } 109 | 110 | private static void OnDeviceChanged(object sender, DeviceDataEventArgs e) 111 | { 112 | DeviceList = new AdvancedAdbClient().GetDevices(); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /WSATools/WSATools/Styles/Button.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 87 | -------------------------------------------------------------------------------- /WSATools/WSATools/Helpers/UIHelper.cs: -------------------------------------------------------------------------------- 1 | using ModernWpf.Media.Animation; 2 | using System; 3 | using System.Collections.ObjectModel; 4 | using System.Drawing; 5 | using System.Threading.Tasks; 6 | using WSATools.Pages; 7 | 8 | namespace WSATools.Helpers 9 | { 10 | internal static class UIHelper 11 | { 12 | public const string Error = ""; 13 | public const string Seccess = ""; 14 | public const string Message = ""; 15 | public const string Warnning = ""; 16 | public const string AppTitle = "Universal-like Minecraft Launcher"; 17 | 18 | public static float DpiX, DpiY; 19 | public static MainPage MainPage; 20 | public static MainWindow MainWindow; 21 | public static bool IsShowingProgressRing, IsShowingProgressBar, IsShowingMessage; 22 | private static readonly ObservableCollection<(string message, string info, MainPage.MessageColor color)> MessageList = new(); 23 | 24 | public enum NavigationThemeTransition 25 | { 26 | Default, 27 | Entrance, 28 | DrillIn, 29 | Suppress 30 | } 31 | 32 | static UIHelper() 33 | { 34 | Graphics graphics = Graphics.FromHwnd(IntPtr.Zero); 35 | DpiX = graphics.DpiX / 96; 36 | DpiY = graphics.DpiY / 96; 37 | } 38 | 39 | public static void Navigate(Type pageType, object e = null, NavigationThemeTransition Type = NavigationThemeTransition.Default) 40 | { 41 | _ = Type switch 42 | { 43 | NavigationThemeTransition.DrillIn => MainPage?.NavigationViewFrame.Navigate(pageType, e, new DrillInNavigationTransitionInfo()), 44 | NavigationThemeTransition.Entrance => MainPage?.NavigationViewFrame.Navigate(pageType, e, new EntranceNavigationTransitionInfo()), 45 | NavigationThemeTransition.Suppress => MainPage?.NavigationViewFrame.Navigate(pageType, e, new SuppressNavigationTransitionInfo()), 46 | NavigationThemeTransition.Default => MainPage?.NavigationViewFrame.Navigate(pageType, e), 47 | _ => MainPage?.NavigationViewFrame.Navigate(pageType, e), 48 | }; 49 | } 50 | 51 | /// 52 | /// 显示进度环 53 | /// 54 | public static void ShowProgressRing() 55 | { 56 | IsShowingProgressRing = true; 57 | MainPage.ShowProgressRing(); 58 | } 59 | 60 | /// 61 | /// 隐藏进度环 62 | /// 63 | public static void HideProgressRing() 64 | { 65 | IsShowingProgressRing = false; 66 | MainPage.HideProgressRing(); 67 | } 68 | 69 | /// 70 | /// 显示进度条-正常 71 | /// 72 | public static void ShowProgressBar() 73 | { 74 | IsShowingProgressBar = true; 75 | MainPage.ShowProgressBar(); 76 | } 77 | 78 | /// 79 | /// 显示进度条-暂停 80 | /// 81 | public static void PausedProgressBar() 82 | { 83 | IsShowingProgressBar = true; 84 | MainPage.PausedProgressBar(); 85 | } 86 | 87 | /// 88 | /// 显示进度条-错误 89 | /// 90 | public static void ErrorProgressBar() 91 | { 92 | IsShowingProgressBar = true; 93 | MainPage.ErrorProgressBar(); 94 | } 95 | 96 | /// 97 | /// 隐藏进度条 98 | /// 99 | public static void HideProgressBar() 100 | { 101 | IsShowingProgressBar = false; 102 | MainPage.HideProgressBar(); 103 | } 104 | 105 | /// 106 | /// 展示应用内通知 107 | /// 108 | /// 要展示的消息 109 | /// 消息前的图标 110 | /// 消息前图标的颜色 111 | public static async void ShowMessage(string message, string info = Message, MainPage.MessageColor color = MainPage.MessageColor.Blue) 112 | { 113 | MessageList.Add((message, info, color)); 114 | if (!IsShowingMessage) 115 | { 116 | IsShowingMessage = true; 117 | while (MessageList.Count > 0) 118 | { 119 | if (!string.IsNullOrEmpty(MessageList[0].message)) 120 | { 121 | string messages = $"{MessageList[0].message.Replace("\n", " ")}"; 122 | MainPage.ShowMessage(messages, MessageList[0].info, MessageList[0].color); 123 | await Task.Delay(3000); 124 | } 125 | MessageList.RemoveAt(0); 126 | if (MessageList.Count == 0) 127 | { 128 | MainPage.HideMessage(); 129 | } 130 | } 131 | IsShowingMessage = false; 132 | } 133 | } 134 | 135 | /// 136 | /// 获取时间内的问候语 137 | /// 138 | /// 问候语 139 | public static string GetGreetings() 140 | { 141 | string str = ""; 142 | DateTime now = DateTime.Now; 143 | int times = now.Hour; 144 | if (times is >= 0 and < 6) { str = "熬夜对身体不好哦"; } 145 | if (times is >= 6 and < 9) { str = "早安"; } 146 | if (times is >= 9 and < 11) { str = "上午好"; } 147 | if (times is >= 11 and < 13) { str = "中午好"; } 148 | if (times is >= 13 and < 17) { str = "下午好"; } 149 | if (times is >= 17 and < 19) { str = "吃过晚饭了吗"; } 150 | if (times is >= 19 and < 24) { str = "晚安"; } 151 | return str; 152 | } 153 | 154 | /// 155 | /// 将字节数转换为可读数据 156 | /// 157 | /// 字节数 158 | /// xx.xx xB 159 | public static string GetSizeString(this double size) 160 | { 161 | int index = 0; 162 | while (true) 163 | { 164 | index++; 165 | size /= 1024; 166 | if (size is > 0.7 and < 716.8) { break; } 167 | else if (size >= 716.8) { continue; } 168 | else if (size <= 0.7) 169 | { 170 | size *= 1024; 171 | index--; 172 | break; 173 | } 174 | } 175 | string str = string.Empty; 176 | switch (index) 177 | { 178 | case 0: str = "B"; break; 179 | case 1: str = "KB"; break; 180 | case 2: str = "MB"; break; 181 | case 3: str = "GB"; break; 182 | case 4: str = "TB"; break; 183 | default: 184 | break; 185 | } 186 | return $"{size:N2}{str}"; 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /WSATools/WSATools/Controls/Setting.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Windows; 3 | using System.Windows.Automation; 4 | using System.Windows.Controls; 5 | 6 | namespace WSATools.Controls 7 | { 8 | /// 9 | /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。 10 | /// 11 | /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。 12 | /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 13 | /// 元素中: 14 | /// 15 | /// xmlns:MyNamespace="clr-namespace:WSATools.Controls" 16 | /// 17 | /// 18 | /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。 19 | /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 20 | /// 元素中: 21 | /// 22 | /// xmlns:MyNamespace="clr-namespace:WSATools.Controls;assembly=WSATools.Controls" 23 | /// 24 | /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用, 25 | /// 并重新生成以避免编译错误: 26 | /// 27 | /// 在解决方案资源管理器中右击目标项目,然后依次单击 28 | /// “添加引用”->“项目”->[浏览查找并选择此项目] 29 | /// 30 | /// 31 | /// 步骤 2) 32 | /// 继续操作并在 XAML 文件中使用控件。 33 | /// 34 | /// 35 | /// 36 | /// 37 | [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")] 38 | [TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")] 39 | [TemplatePart(Name = RightIconPresenter, Type = typeof(Border))] 40 | [TemplatePart(Name = PartIconPresenter, Type = typeof(ContentPresenter))] 41 | [TemplatePart(Name = PartDescriptionPresenter, Type = typeof(ContentPresenter))] 42 | public class Setting : ContentControl 43 | { 44 | private const string PartIconPresenter = "IconPresenter"; 45 | private const string PartDescriptionPresenter = "DescriptionPresenter"; 46 | private const string RightIconPresenter = "ExpandCollapseChevronBorder"; 47 | private Border _rightIconPresenter; 48 | private ContentPresenter _iconPresenter; 49 | private ContentPresenter _descriptionPresenter; 50 | private Setting _setting; 51 | 52 | public Setting() 53 | { 54 | DefaultStyleKey = typeof(Setting); 55 | } 56 | 57 | public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register( 58 | "Header", 59 | typeof(string), 60 | typeof(Setting), 61 | new PropertyMetadata(default(string), OnHeaderChanged)); 62 | 63 | public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register( 64 | "Description", 65 | typeof(object), 66 | typeof(Setting), 67 | new PropertyMetadata(null, OnDescriptionChanged)); 68 | 69 | public static readonly DependencyProperty IconProperty = DependencyProperty.Register( 70 | "Icon", 71 | typeof(object), 72 | typeof(Setting), 73 | new PropertyMetadata(default(string), OnIconChanged)); 74 | 75 | public static readonly DependencyProperty RightIconProperty = DependencyProperty.Register( 76 | "RightIcon", 77 | typeof(string), 78 | typeof(Setting), 79 | new PropertyMetadata(null, OnIconChanged)); 80 | 81 | public static readonly DependencyProperty ActionContentProperty = DependencyProperty.Register( 82 | "ActionContent", 83 | typeof(object), 84 | typeof(Setting), 85 | null); 86 | 87 | //public static readonly DependencyProperty RightIconVisibilityProperty = DependencyProperty.Register( 88 | // "RightIconVisibility", 89 | // typeof(Visibility), 90 | // typeof(Setting), 91 | // new PropertyMetadata(null, OnIconChanged)); 92 | 93 | [Localizable(true)] 94 | public string Header 95 | { 96 | get => (string)GetValue(HeaderProperty); 97 | set => SetValue(HeaderProperty, value); 98 | } 99 | 100 | [Localizable(true)] 101 | public object Description 102 | { 103 | get => GetValue(DescriptionProperty); 104 | set => SetValue(DescriptionProperty, value); 105 | } 106 | 107 | public object Icon 108 | { 109 | get => GetValue(IconProperty); 110 | set => SetValue(IconProperty, value); 111 | } 112 | 113 | public string RightIcon 114 | { 115 | get => (string)GetValue(RightIconProperty); 116 | set => SetValue(RightIconProperty, value); 117 | } 118 | 119 | public object ActionContent 120 | { 121 | get => GetValue(ActionContentProperty); 122 | set => SetValue(ActionContentProperty, value); 123 | } 124 | 125 | //public Visibility RightIconVisibility 126 | //{ 127 | // get => (Visibility)GetValue(RightIconVisibilityProperty); 128 | // set => SetValue(RightIconVisibilityProperty, value); 129 | //} 130 | 131 | public override void OnApplyTemplate() 132 | { 133 | IsEnabledChanged -= Setting_IsEnabledChanged; 134 | _setting = this; 135 | _rightIconPresenter = (Border)_setting.GetTemplateChild(RightIconPresenter); 136 | _iconPresenter = (ContentPresenter)_setting.GetTemplateChild(PartIconPresenter); 137 | _descriptionPresenter = (ContentPresenter)_setting.GetTemplateChild(PartDescriptionPresenter); 138 | Update(); 139 | SetEnabledState(); 140 | IsEnabledChanged += Setting_IsEnabledChanged; 141 | base.OnApplyTemplate(); 142 | } 143 | 144 | private static void OnHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 145 | { 146 | ((Setting)d).Update(); 147 | } 148 | 149 | private static void OnIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 150 | { 151 | ((Setting)d).Update(); 152 | } 153 | 154 | private static void OnDescriptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 155 | { 156 | ((Setting)d).Update(); 157 | } 158 | 159 | private void Setting_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) 160 | { 161 | SetEnabledState(); 162 | } 163 | 164 | private void SetEnabledState() 165 | { 166 | VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true); 167 | } 168 | 169 | private void Update() 170 | { 171 | if (_setting == null) 172 | { 173 | return; 174 | } 175 | 176 | if (_setting.ActionContent != null) 177 | { 178 | if (_setting.ActionContent.GetType() != typeof(Button)) 179 | { 180 | // We do not want to override the default AutomationProperties.Name of a button. Its Content property already describes what it does. 181 | if (!string.IsNullOrEmpty(_setting.Header)) 182 | { 183 | AutomationProperties.SetName((UIElement)_setting.ActionContent, _setting.Header); 184 | } 185 | } 186 | } 187 | 188 | if (_setting._iconPresenter != null) 189 | { 190 | if (_setting.Icon == null) 191 | { 192 | _setting._iconPresenter.Visibility = Visibility.Collapsed; 193 | } 194 | else 195 | { 196 | _setting._iconPresenter.Visibility = Visibility.Visible; 197 | } 198 | } 199 | 200 | if (_setting.RightIcon == null) 201 | { 202 | _setting._rightIconPresenter.Visibility = Visibility.Collapsed; 203 | } 204 | else 205 | { 206 | _setting._rightIconPresenter.Visibility = Visibility.Visible; 207 | } 208 | 209 | if (_setting.Description == null) 210 | { 211 | _setting._descriptionPresenter.Visibility = Visibility.Collapsed; 212 | } 213 | else 214 | { 215 | _setting._descriptionPresenter.Visibility = Visibility.Visible; 216 | } 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /WSATools/WSATools/Styles/Setting.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 77 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 104 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /WSATools/WSATools/Pages/HomePage.xaml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 29 | 30 | 31 | 36 | 41 | 42 | 43 | 44 | 45 | 46 | 51 | 52 | 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /WSATools/WSATools.Package/WSATools.Package.wapproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15.0 5 | 6 | 7 | 8 | Debug 9 | x86 10 | 11 | 12 | Release 13 | x86 14 | 15 | 16 | Debug 17 | x64 18 | 19 | 20 | Release 21 | x64 22 | 23 | 24 | Debug 25 | ARM 26 | 27 | 28 | Release 29 | ARM 30 | 31 | 32 | Debug 33 | ARM64 34 | 35 | 36 | Release 37 | ARM64 38 | 39 | 40 | Debug 41 | AnyCPU 42 | 43 | 44 | Release 45 | AnyCPU 46 | 47 | 48 | 49 | $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ 50 | 51 | 52 | 53 | 2d2b8ac2-e1ca-4d65-9a12-4cc863008d20 54 | 10.0.22000.0 55 | 10.0.14393.0 56 | zh-CN 57 | True 58 | $(NoWarn);NU1702 59 | 0CDF4A03E9BE9DD789894BB3C7AD3DEDECD9AB25 60 | False 61 | http://timestamp.digicert.com 62 | SHA256 63 | False 64 | True 65 | neutral 66 | 0 67 | ..\WSATools\WSATools.csproj 68 | 69 | 70 | Always 71 | 72 | 73 | Always 74 | 75 | 76 | Always 77 | 78 | 79 | Always 80 | 81 | 82 | Always 83 | 84 | 85 | Always 86 | 87 | 88 | Always 89 | 90 | 91 | Always 92 | 93 | 94 | Always 95 | 96 | 97 | Always 98 | 99 | 100 | 101 | Designer 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /WSATools/WSATools/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks 13 | 14 | 15 | 16 | 17 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. 18 | 19 | 20 | 21 | 22 | A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks 23 | 24 | 25 | 26 | 27 | A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. 28 | 29 | 30 | 31 | 32 | A list of unmanaged 32 bit assembly names to include, delimited with line breaks. 33 | 34 | 35 | 36 | 37 | A list of unmanaged 64 bit assembly names to include, delimited with line breaks. 38 | 39 | 40 | 41 | 42 | The order of preloaded assemblies, delimited with line breaks. 43 | 44 | 45 | 46 | 47 | 48 | This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. 49 | 50 | 51 | 52 | 53 | Controls if .pdbs for reference assemblies are also embedded. 54 | 55 | 56 | 57 | 58 | Controls if runtime assemblies are also embedded. 59 | 60 | 61 | 62 | 63 | Controls whether the runtime assemblies are embedded with their full path or only with their assembly name. 64 | 65 | 66 | 67 | 68 | Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. 69 | 70 | 71 | 72 | 73 | As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. 74 | 75 | 76 | 77 | 78 | Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. 79 | 80 | 81 | 82 | 83 | Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. 84 | 85 | 86 | 87 | 88 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | 89 | 90 | 91 | 92 | 93 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. 94 | 95 | 96 | 97 | 98 | A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with | 99 | 100 | 101 | 102 | 103 | A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |. 104 | 105 | 106 | 107 | 108 | A list of unmanaged 32 bit assembly names to include, delimited with |. 109 | 110 | 111 | 112 | 113 | A list of unmanaged 64 bit assembly names to include, delimited with |. 114 | 115 | 116 | 117 | 118 | The order of preloaded assemblies, delimited with |. 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 127 | 128 | 129 | 130 | 131 | A comma-separated list of error codes that can be safely ignored in assembly verification. 132 | 133 | 134 | 135 | 136 | 'false' to turn off automatic generation of the XML Schema file. 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /WSATools/WSATools/Pages/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using ModernWpf; 2 | using ModernWpf.Controls; 3 | using ModernWpf.Media.Animation; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Windows; 8 | using System.Windows.Media; 9 | using System.Windows.Navigation; 10 | using WSATools.Controls; 11 | using WSATools.Helpers; 12 | using WSATools.Pages.SettingsPages; 13 | 14 | namespace WSATools.Pages 15 | { 16 | /// 17 | /// MainPage.xaml 的交互逻辑 18 | /// 19 | public partial class MainPage : Page 20 | { 21 | public PageHeader PageHeader => NavigationView.FindDescendant(); 22 | 23 | private readonly List<(string Tag, Type Page)> _pages = new() 24 | { 25 | ("Home", typeof(HomePage)), 26 | ("Apps", typeof(AppsPage)), 27 | }; 28 | 29 | public MainPage() 30 | { 31 | InitializeComponent(); 32 | UIHelper.MainPage = this; 33 | NavigationView.PaneDisplayMode = NavigationViewPaneDisplayMode.Left; 34 | } 35 | 36 | private void NavigationView_Loaded(object sender, RoutedEventArgs e) 37 | { 38 | // Add handler for ContentFrame navigation. 39 | NavigationViewFrame.Navigated += On_Navigated; 40 | NavigationView.SelectedItem = NavigationView.MenuItems[0]; 41 | NavigationView.PaneDisplayMode = NavigationViewPaneDisplayMode.Auto; 42 | } 43 | 44 | private void NavigationView_Navigate(string NavItemTag, NavigationTransitionInfo TransitionInfo) 45 | { 46 | Type _page = null; 47 | if (NavItemTag == "settings") 48 | { 49 | _page = typeof(SettingsPage); 50 | } 51 | else 52 | { 53 | (string Tag, Type Page) item = _pages.FirstOrDefault(p => p.Tag.Equals(NavItemTag, StringComparison.Ordinal)); 54 | _page = item.Page; 55 | } 56 | // Get the page type before navigation so you can prevent duplicate 57 | // entries in the backstack. 58 | Type PreNavPageType = NavigationViewFrame.CurrentSourcePageType; 59 | 60 | // Only navigate if the selected page isn't currently loaded. 61 | if (!(_page is null) && !Equals(PreNavPageType, _page)) 62 | { 63 | _ = NavigationViewFrame.Navigate(_page, null, TransitionInfo); 64 | } 65 | } 66 | 67 | private void NavigationView_BackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args) => _ = TryGoBack(); 68 | 69 | private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) 70 | { 71 | if (args.IsSettingsSelected) 72 | { 73 | _ = NavigationViewFrame.Navigate(typeof(SettingsPage), null, args.RecommendedNavigationTransitionInfo); 74 | } 75 | else if (args.SelectedItemContainer != null) 76 | { 77 | string NavItemTag = args.SelectedItemContainer.Tag.ToString(); 78 | NavigationView_Navigate(NavItemTag, args.RecommendedNavigationTransitionInfo); 79 | } 80 | } 81 | 82 | private bool TryGoBack() 83 | { 84 | if (!NavigationViewFrame.CanGoBack) 85 | { return false; } 86 | 87 | // Don't go back if the nav pane is overlayed. 88 | if (NavigationView.IsPaneOpen && 89 | (NavigationView.DisplayMode == NavigationViewDisplayMode.Compact || 90 | NavigationView.DisplayMode == NavigationViewDisplayMode.Minimal)) 91 | { return false; } 92 | 93 | NavigationViewFrame.GoBack(); 94 | return true; 95 | } 96 | 97 | private void On_Navigated(object _, NavigationEventArgs e) 98 | { 99 | NavigationView.IsBackEnabled = NavigationViewFrame.CanGoBack; 100 | if (NavigationViewFrame.SourcePageType == typeof(SettingsPage)) 101 | { 102 | // SettingsItem is not part of NavView.MenuItems, and doesn't have a Tag. 103 | NavigationView.SelectedItem = (NavigationViewItem)NavigationView.SettingsItem; 104 | NavigationView.Header = "设置"; 105 | } 106 | else if (NavigationViewFrame.SourcePageType == typeof(TestPage)) 107 | { 108 | NavigationView.Header = "测试"; 109 | } 110 | else if (NavigationViewFrame.SourcePageType != null) 111 | { 112 | (string Tag, Type Page) item = _pages.FirstOrDefault(p => p.Page == e.Content.GetType()); 113 | 114 | try 115 | { 116 | NavigationView.SelectedItem = NavigationView.MenuItems 117 | .OfType() 118 | .First(n => n.Tag.Equals(item.Tag)); 119 | } 120 | catch 121 | { 122 | try 123 | { 124 | NavigationView.SelectedItem = NavigationView.FooterMenuItems 125 | .OfType() 126 | .First(n => n.Tag.Equals(item.Tag)); 127 | } 128 | catch { } 129 | } 130 | 131 | NavigationView.Header = (((NavigationViewItem)NavigationView.SelectedItem)?.Content?.ToString()); 132 | } 133 | } 134 | 135 | private void NavigationViewControl_PaneClosing(NavigationView sender, NavigationViewPaneClosingEventArgs args) 136 | { 137 | UpdateAppTitleMargin(sender); 138 | } 139 | 140 | private void NavigationViewControl_PaneOpening(NavigationView sender, object args) 141 | { 142 | UpdateAppTitleMargin(sender); 143 | } 144 | 145 | private void NavigationViewControl_DisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args) 146 | { 147 | Thickness currMargin = AppTitleBar.Margin; 148 | 149 | AppTitleBar.Margin = sender.DisplayMode == NavigationViewDisplayMode.Minimal && 150 | sender.IsBackButtonVisible != NavigationViewBackButtonVisible.Collapsed 151 | ? new Thickness((sender.CompactPaneLength * 2) - 8, currMargin.Top, currMargin.Right, currMargin.Bottom) 152 | : new Thickness(sender.CompactPaneLength, currMargin.Top, currMargin.Right, currMargin.Bottom); 153 | 154 | UpdateAppTitleMargin(sender); 155 | UpdateHeaderMargin(sender); 156 | } 157 | 158 | private void UpdateAppTitleMargin(NavigationView sender) 159 | { 160 | const int smallLeftIndent = 4, largeLeftIndent = 24; 161 | 162 | Thickness currMargin = AppTitle.Margin; 163 | 164 | AppTitle.Margin = (sender.DisplayMode == NavigationViewDisplayMode.Expanded && sender.IsPaneOpen) || 165 | (sender.DisplayMode == NavigationViewDisplayMode.Compact && sender.IsPaneOpen) || 166 | sender.DisplayMode == NavigationViewDisplayMode.Minimal 167 | ? new Thickness(smallLeftIndent, currMargin.Top, currMargin.Right, currMargin.Bottom) 168 | : new Thickness(largeLeftIndent, currMargin.Top, currMargin.Right, currMargin.Bottom); 169 | } 170 | 171 | private void UpdateHeaderMargin(NavigationView sender) 172 | { 173 | if (PageHeader != null) 174 | { 175 | PageHeader.HeaderPadding = sender.DisplayMode == NavigationViewDisplayMode.Minimal 176 | ? (Thickness)Application.Current.Resources["PageHeaderMinimalPadding"] 177 | : (Thickness)Application.Current.Resources["PageHeaderDefaultPadding"]; 178 | 179 | Thickness currMargin = PageHeader.Margin; 180 | 181 | PageHeader.Margin = sender.DisplayMode == NavigationViewDisplayMode.Minimal && 182 | sender.IsBackButtonVisible != NavigationViewBackButtonVisible.Collapsed 183 | ? new Thickness(-sender.CompactPaneLength + 8, currMargin.Top, currMargin.Right, currMargin.Bottom) 184 | : new Thickness(0, currMargin.Top, currMargin.Right, currMargin.Bottom); 185 | } 186 | } 187 | 188 | #region 状态栏 189 | public enum MessageColor 190 | { 191 | Red, 192 | Blue, 193 | Green, 194 | Yellow, 195 | } 196 | 197 | public void ShowProgressRing() 198 | { 199 | if (PageHeader != null) 200 | { 201 | PageHeader.ProgressRing.Visibility = Visibility.Visible; 202 | PageHeader.ProgressRing.IsActive = true; 203 | } 204 | } 205 | 206 | public void HideProgressRing() 207 | { 208 | if (PageHeader != null) 209 | { 210 | PageHeader.ProgressRing.IsActive = false; 211 | PageHeader.ProgressRing.Visibility = Visibility.Collapsed; 212 | } 213 | } 214 | 215 | public void ShowProgressBar() 216 | { 217 | ProgressBar.Visibility = Visibility.Visible; 218 | ProgressBar.IsIndeterminate = true; 219 | ProgressBar.ShowError = false; 220 | ProgressBar.ShowPaused = false; 221 | } 222 | 223 | public void PausedProgressBar() 224 | { 225 | ProgressBar.Visibility = Visibility.Visible; 226 | ProgressBar.IsIndeterminate = true; 227 | ProgressBar.ShowError = false; 228 | ProgressBar.ShowPaused = true; 229 | } 230 | 231 | public void ErrorProgressBar() 232 | { 233 | ProgressBar.Visibility = Visibility.Visible; 234 | ProgressBar.IsIndeterminate = true; 235 | ProgressBar.ShowPaused = false; 236 | ProgressBar.ShowError = true; 237 | } 238 | 239 | public void HideProgressBar() 240 | { 241 | ProgressBar.Visibility = Visibility.Collapsed; 242 | ProgressBar.IsIndeterminate = false; 243 | ProgressBar.ShowError = false; 244 | ProgressBar.ShowPaused = false; 245 | } 246 | 247 | public void ShowMessage(string message, string info, MessageColor color) 248 | { 249 | if (PageHeader != null) 250 | { 251 | PageHeader.Message.Text = message; 252 | PageHeader.MessageInfo.Glyph = info; 253 | PageHeader.MessageInfo.Foreground = color switch 254 | { 255 | MessageColor.Red => new SolidColorBrush(Color.FromArgb(255, 245, 88, 98)), 256 | MessageColor.Blue => new SolidColorBrush(Color.FromArgb(255, 119, 220, 255)), 257 | MessageColor.Green => new SolidColorBrush(Color.FromArgb(255, 155, 230, 155)), 258 | MessageColor.Yellow => new SolidColorBrush(Color.FromArgb(255, 254, 228, 160)), 259 | _ => new SolidColorBrush(Colors.Yellow), 260 | }; 261 | PageHeader?.RectanglePointerEntered(); 262 | } 263 | } 264 | 265 | public void HideMessage() 266 | { 267 | PageHeader?.RectanglePointerExited(); 268 | } 269 | 270 | #endregion 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /WSATools/WSATools/Styles/SettingExpander.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 0 8 | 56, 8, 40, 8 9 | 10 | Transparent 11 | 12 | 13 | 14 | 22 | 23 | 0,0,8,0 24 | 25 | 26 | 33 | 34 | 35 | 45 | 46 | 50 | 51 | 113 | 114 | 193 | 194 |