├── .gitattributes
├── .gitignore
├── ADB Explorer.sln
├── ADB Explorer
├── ADB Explorer.csproj
├── App.xaml
├── App.xaml.cs
├── AssemblyInfo.cs
├── Controls
│ ├── Icons
│ │ ├── InstallIcon.xaml
│ │ ├── InstallIcon.xaml.cs
│ │ ├── PathIcon.xaml
│ │ ├── PathIcon.xaml.cs
│ │ ├── PullIcon.xaml
│ │ ├── PullIcon.xaml.cs
│ │ ├── PushIcon.xaml
│ │ ├── PushIcon.xaml.cs
│ │ ├── RecycleIcon.xaml
│ │ ├── RecycleIcon.xaml.cs
│ │ ├── UninstallIcon.xaml
│ │ └── UninstallIcon.xaml.cs
│ ├── MaskedTextBox.xaml
│ ├── MaskedTextBox.xaml.cs
│ ├── NavigationBox.xaml
│ ├── NavigationBox.xaml.cs
│ ├── PasteAndPullTooltip.xaml
│ ├── PasteAndPullTooltip.xaml.cs
│ ├── RenameTooltip.xaml
│ ├── RenameTooltip.xaml.cs
│ ├── ResetSettingsIcon.xaml
│ ├── ResetSettingsIcon.xaml.cs
│ ├── SearchBox.xaml
│ ├── SearchBox.xaml.cs
│ ├── SplashScreen.xaml
│ ├── SplashScreen.xaml.cs
│ ├── TransferIndicator.xaml
│ └── TransferIndicator.xaml.cs
├── Converters
│ ├── CellConverter.cs
│ ├── CompletedStatsConverter.cs
│ ├── ControlSize.cs
│ ├── DoubleEquals.cs
│ ├── EnumToBooleanConverter.cs
│ ├── FileOpProgressConverter.cs
│ ├── FileOpTreeStatusConverter.cs
│ ├── MarginConverter.cs
│ ├── MenuItemConverter.cs
│ ├── SizeConverter.cs
│ ├── StringFormatConverter.cs
│ ├── TreeViewIndentConverter.cs
│ └── TrimmedTooltipConverter.cs
├── DragWindow.xaml
├── DragWindow.xaml.cs
├── Helpers
│ ├── AdbHelper.cs
│ ├── AppInfra
│ │ ├── AsyncHelper.cs
│ │ ├── ByteHelper.cs
│ │ ├── CommandHandler.cs
│ │ ├── DictionaryHelper.cs
│ │ ├── ListHelper.cs
│ │ ├── ObservableList.cs
│ │ ├── ObservableProperty.cs
│ │ ├── RandomString.cs
│ │ └── SettingsHelper.cs
│ ├── Attachable
│ │ ├── DialogHelper.cs
│ │ ├── ExpanderHelper.cs
│ │ ├── MenuHelper.cs
│ │ ├── SelectionHelper.cs
│ │ ├── StyleHelper.cs
│ │ ├── TextHelper.cs
│ │ └── VisibilityHelper.cs
│ ├── DeviceHelper.cs
│ ├── DriveHelper.cs
│ ├── ExplorerHelper.cs
│ ├── File
│ │ ├── FileHelper.cs
│ │ ├── FileToIcon.cs
│ │ ├── FolderHelper.cs
│ │ └── TrashHelper.cs
│ ├── FileOp
│ │ ├── FileOpTest.cs
│ │ ├── FinishedTestOperation.cs
│ │ └── InProgressTestOperation.cs
│ ├── QrGenerator.cs
│ └── TemplateSelectors
│ │ ├── DeviceTemplateSelector.cs
│ │ ├── DriveTemplateSelector.cs
│ │ ├── FileOpFileNameTemplateSelector.cs
│ │ ├── FileOpProgressTemplateSelector.cs
│ │ ├── FileOpTreeTemplateSelector.cs
│ │ ├── FileOperationTemplateSelector.cs
│ │ ├── MenuTemplateSelector.cs
│ │ ├── SettingsGroupTemplateSelector.cs
│ │ └── SettingsTemplateSelector.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Models
│ ├── Battery.cs
│ ├── Device
│ │ ├── Device.cs
│ │ ├── HistoryDevice.cs
│ │ ├── LogicalDevice.cs
│ │ ├── NewDevice.cs
│ │ ├── ServiceDevice.cs
│ │ └── WsaPkgDevice.cs
│ ├── DirectoryLister.cs
│ ├── Drive
│ │ ├── Drive.cs
│ │ ├── LogicalDrive.cs
│ │ └── VirtualDrive.cs
│ ├── File
│ │ ├── FileClass.cs
│ │ ├── FilePath.cs
│ │ ├── FileStat.cs
│ │ ├── IBaseFile.cs
│ │ ├── Package.cs
│ │ ├── SyncFile.cs
│ │ └── TrashIndexer.cs
│ ├── FileOpColumnConfig.cs
│ ├── FileOpFilter.cs
│ ├── Log.cs
│ └── Static
│ │ ├── AdbRegEx.cs
│ │ ├── Const.cs
│ │ ├── Data.cs
│ │ └── NavHistory.cs
├── PortableLauncher.bat
├── Properties
│ ├── AppGlobal.Designer.cs
│ └── AppGlobal.resx
├── Resources
│ ├── APK_format_icon_2014-2019_.ico
│ ├── AdbProgressRedirection_ARM
│ ├── AdbProgressRedirection_x86
│ ├── Fonts
│ │ └── Nunito-VariableFont_wght.ttf
│ └── Links.cs
├── Services
│ ├── ADB
│ │ ├── ADBDevice.cs
│ │ ├── ADBService.cs
│ │ ├── FileOpProgressInfo.cs
│ │ ├── MDNS.cs
│ │ ├── ShellCommands.cs
│ │ └── WiFiPairingService.cs
│ ├── AppInfra
│ │ ├── AppRuntimeSettings.cs
│ │ ├── AppSettings.cs
│ │ ├── CopyPasteService.cs
│ │ ├── DebugLog.cs
│ │ ├── DialogService.cs
│ │ ├── FileAction
│ │ │ ├── ActionMenu.cs
│ │ │ ├── FileAction.cs
│ │ │ ├── FileActionLogic.cs
│ │ │ ├── FileActionsEnable.cs
│ │ │ ├── ToggleMenu.cs
│ │ │ └── ToolBar.cs
│ │ ├── IpcService.cs
│ │ ├── LowLevel
│ │ │ ├── DataFormats.cs
│ │ │ ├── DiskUsage.cs
│ │ │ ├── ExplorerWindow.cs
│ │ │ ├── FileContentsStream.cs
│ │ │ ├── FileDescriptor.cs
│ │ │ ├── MonitorInfo.cs
│ │ │ ├── ProcessHandling.cs
│ │ │ ├── ThemeService.cs
│ │ │ ├── VirtualFileDataObject.cs
│ │ │ └── WindowStyle.cs
│ │ ├── NativeMethods
│ │ │ ├── DragDropNative.cs
│ │ │ ├── ExplorerWatcher.cs
│ │ │ ├── InterceptClipboard.cs
│ │ │ ├── InterceptMouse.cs
│ │ │ ├── NativeMethods.cs
│ │ │ ├── SysImageList.cs
│ │ │ └── UnusedNativeCode.cs
│ │ ├── Network.cs
│ │ ├── Security.cs
│ │ ├── SettingsModel.cs
│ │ └── Storage.cs
│ └── FileOperation
│ │ ├── FileArchiveOperation.cs
│ │ ├── FileChangeModifiedOperation.cs
│ │ ├── FileDeleteOperation.cs
│ │ ├── FileMoveOperation.cs
│ │ ├── FileOperation.cs
│ │ ├── FileOperationQueue.cs
│ │ ├── FileRenameOperation.cs
│ │ ├── FileSyncOperation.cs
│ │ ├── PackageInstallOperation.cs
│ │ └── ShellFileOperation.cs
├── Strings
│ ├── Resources.Designer.cs
│ ├── Resources.ar.resx
│ ├── Resources.bn.resx
│ ├── Resources.de.resx
│ ├── Resources.es-419.resx
│ ├── Resources.fa.resx
│ ├── Resources.fr.resx
│ ├── Resources.he.resx
│ ├── Resources.id.resx
│ ├── Resources.it.resx
│ ├── Resources.ja.resx
│ ├── Resources.ko.resx
│ ├── Resources.pl.resx
│ ├── Resources.pt-BR.resx
│ ├── Resources.resx
│ ├── Resources.ru.resx
│ ├── Resources.tr.resx
│ ├── Resources.zh-CN.resx
│ └── Resources.zh-TW.resx
├── Styles
│ ├── BasicStyles.xaml
│ ├── Colors.xaml
│ ├── Controls
│ │ ├── Button.xaml
│ │ ├── CheckBox.xaml
│ │ ├── ComboBox.xaml
│ │ ├── ContentDialog.xaml
│ │ ├── ContextMenu.xaml
│ │ ├── DataGrid.xaml
│ │ ├── Expander.xaml
│ │ ├── MenuItem.xaml
│ │ ├── RadioButton.xaml
│ │ ├── ScrollBar.xaml
│ │ ├── ScrollViewer.xaml
│ │ ├── SplitView.xaml
│ │ ├── TextBox.xaml
│ │ └── ToggleButton.xaml
│ ├── CustomStyles.xaml
│ ├── Device.xaml
│ ├── Drive.xaml
│ ├── FileAction.xaml
│ ├── FileOp.xaml
│ ├── FileOpColumn.xaml
│ └── Settings.xaml
├── Usings.cs
├── ViewModels
│ ├── Device
│ │ ├── DeviceAction.cs
│ │ ├── DeviceViewModel.cs
│ │ ├── Devices.cs
│ │ ├── HistoryDeviceViewModel.cs
│ │ ├── LogicalDeviceViewModel.cs
│ │ ├── NewDeviceViewModel.cs
│ │ ├── ServiceDeviceViewModel.cs
│ │ └── WsaPkgDeviceViewModel.cs
│ ├── Drive
│ │ ├── DriveViewModel.cs
│ │ ├── LogicalDriveViewModel.cs
│ │ └── VirtualDriveViewModel.cs
│ ├── FileOp
│ │ ├── CanceledOpProgressViewModel.cs
│ │ ├── CompletedShellProgressViewModel.cs
│ │ ├── CompletedSyncProgressViewModel.cs
│ │ ├── FailedOpProgressViewModel.cs
│ │ ├── FileOpProgressViewModel.cs
│ │ ├── InProgShellProgressViewModel.cs
│ │ ├── InProgSyncProgressViewModel.cs
│ │ └── WaitingOpProgressViewModel.cs
│ └── ViewModelBase.cs
├── Views
│ ├── Battery
│ │ ├── CompactBatteryControl.xaml
│ │ ├── CompactBatteryControl.xaml.cs
│ │ ├── DetailedBatteryControl.xaml
│ │ └── DetailedBatteryControl.xaml.cs
│ ├── Device
│ │ ├── HistoryDeviceControl.xaml
│ │ ├── HistoryDeviceControl.xaml.cs
│ │ ├── LogicalDeviceControl.xaml
│ │ ├── LogicalDeviceControl.xaml.cs
│ │ ├── NewDeviceControl.xaml
│ │ ├── NewDeviceControl.xaml.cs
│ │ ├── ServiceDeviceControl.xaml
│ │ ├── ServiceDeviceControl.xaml.cs
│ │ ├── WsaPkgDeviceControl.xaml
│ │ └── WsaPkgDeviceControl.xaml.cs
│ └── Drive
│ │ ├── LogicalDriveControl.xaml
│ │ ├── LogicalDriveControl.xaml.cs
│ │ ├── VirtualDriveControl.xaml
│ │ └── VirtualDriveControl.xaml.cs
├── app.manifest
├── app_icon_2023_combined.ico
└── app_icon_black_2023_256px.png
├── ADB Package
├── ADB_Package.wapproj
├── Images
│ ├── 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
│ ├── SplashScreen.scale-100.png
│ ├── SplashScreen.scale-125.png
│ ├── SplashScreen.scale-150.png
│ ├── SplashScreen.scale-200.png
│ ├── SplashScreen.scale-400.png
│ ├── Square150x150Logo.scale-100.png
│ ├── Square150x150Logo.scale-125.png
│ ├── Square150x150Logo.scale-150.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square150x150Logo.scale-400.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-256.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-48.png
│ ├── Square44x44Logo.altform-unplated_targetsize-16.png
│ ├── Square44x44Logo.altform-unplated_targetsize-256.png
│ ├── Square44x44Logo.altform-unplated_targetsize-32.png
│ ├── Square44x44Logo.altform-unplated_targetsize-48.png
│ ├── Square44x44Logo.scale-100.png
│ ├── Square44x44Logo.scale-125.png
│ ├── Square44x44Logo.scale-150.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.scale-400.png
│ ├── Square44x44Logo.targetsize-16.png
│ ├── Square44x44Logo.targetsize-24.png
│ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── Square44x44Logo.targetsize-256.png
│ ├── Square44x44Logo.targetsize-32.png
│ ├── Square44x44Logo.targetsize-48.png
│ ├── StoreLogo.scale-100.png
│ ├── StoreLogo.scale-125.png
│ ├── StoreLogo.scale-150.png
│ ├── StoreLogo.scale-200.png
│ ├── StoreLogo.scale-400.png
│ ├── Wide310x150Logo.scale-100.png
│ ├── Wide310x150Logo.scale-125.png
│ ├── Wide310x150Logo.scale-150.png
│ ├── Wide310x150Logo.scale-200.png
│ └── Wide310x150Logo.scale-400.png
├── Package.appxmanifest
└── Strings
│ └── en-us
│ └── Resources.resw
├── ADB_Test
├── ADB_Test.csproj
└── Tests.cs
├── AdbProgressRedirection
├── .vscode
│ ├── settings.json
│ └── tasks.json
├── AdbProgressRedirection.vcxproj
├── AdbProgressRedirection.vcxproj.filters
├── main.cpp
└── output
│ └── .placeholder
├── FUNDING.yml
├── LICENSE
├── Privacy.md
├── README.md
├── ResXCleaner
├── Program.cs
└── ResxCleaner.csproj
├── icons
├── APK_format_icon_(2014-2019).png
├── APK_format_icon_2014-2019_.ico
├── App_icon.pdn
├── Store_icon.png
├── Store_icon_2023.png
├── Store_icon_beta.png
├── Store_icon_beta_2023.png
├── Store_icon_v2.png
├── Store_icon_v3.png
├── adb_explorer_icon_v2_icons8.ico
├── adb_explorer_icon_v2_icons8.pdn
├── adb_explorer_icon_v2_icons8.png
├── adb_explorer_icon_v3_icons8.png
├── adb_explorer_icon_v3_icons8_tile.png
├── adb_explorer_icon_v4_icons8.ico
├── adb_explorer_icon_v4_icons8.png
├── adb_explorer_icon_v4_icons8_combined.ico
├── adb_explorer_icon_v4_icons8_inverted - Copy.png
├── adb_explorer_icon_v4_icons8_inverted.png
├── adb_explorer_icon_v4_icons8_medium.png
├── adb_explorer_icon_v4_icons8_medium_v2.png
├── adb_explorer_icon_v4_icons8_medium_white.png
├── adb_explorer_icon_v4_icons8_simple _white.png
├── adb_explorer_icon_v4_icons8_simple.ico
├── adb_explorer_icon_v4_icons8_simple.png
├── adb_explorer_icon_v4_icons8_simple_v2.png
├── adb_explorer_icon_v4_icons8_tile.png
├── adb_explorer_icon_v5_icons8_combined.ico
├── app_icon_black_2023.png
├── app_icon_black_2023_256px.png
├── app_icon_white_2023.png
├── icons8-android-os-240.png
├── icons8-android-os-250.png
├── icons8-folder-208.png
├── icons8-folder-250.png
├── icons8-sync-100 - Copy.png
├── icons8-sync-100.png
├── icons8_folder&sync&android.png
└── icons8_folder&sync.png
└── licences
├── Android_icon_license.txt
├── Apache License.txt
├── CC BY-SA 3.0.txt
├── LGPLv3.txt
└── icons8.com license.txt
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/ADB Explorer/App.xaml:
--------------------------------------------------------------------------------
1 |
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 |
41 |
42 | Segoe Fluent Icons, Segoe MDL2 Assets
43 | pack://application:,,,/Resources/Fonts/#Nunito
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/ADB Explorer/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | [assembly: ThemeInfo(
2 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
3 | //(used if a resource is not found in the page,
4 | // or application resource dictionaries)
5 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
6 | //(used if a resource is not found in the page,
7 | // app, or any theme specific resource dictionaries)
8 | )]
9 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/InstallIcon.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/InstallIcon.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Controls;
2 |
3 | ///
4 | /// Interaction logic for InstallIcon.xaml
5 | ///
6 | public partial class InstallIcon : UserControl
7 | {
8 | public InstallIcon()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/PathIcon.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
22 |
23 |
24 |
30 |
31 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/PathIcon.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Controls;
2 |
3 | ///
4 | /// Interaction logic for PathIcon.xaml
5 | ///
6 | public partial class PathIcon : UserControl
7 | {
8 | public PathIcon()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/PullIcon.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/PullIcon.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Controls;
2 |
3 | ///
4 | /// Interaction logic for PushIcon.xaml
5 | ///
6 | public partial class PullIcon : UserControl
7 | {
8 | public PullIcon(int spacing = -4)
9 | {
10 | InitializeComponent();
11 |
12 | Spacing = spacing;
13 | }
14 |
15 | public int Spacing
16 | {
17 | get => (int)GetValue(SpacingProperty);
18 | set => SetValue(SpacingProperty, value);
19 | }
20 |
21 | public static readonly DependencyProperty SpacingProperty =
22 | DependencyProperty.Register("Spacing", typeof(int),
23 | typeof(PullIcon), new PropertyMetadata(default(int)));
24 | }
25 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/PushIcon.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/PushIcon.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Controls;
2 |
3 | ///
4 | /// Interaction logic for PushIcon.xaml
5 | ///
6 | public partial class PushIcon : UserControl
7 | {
8 | public PushIcon(int spacing = -4)
9 | {
10 | InitializeComponent();
11 |
12 | Spacing = spacing;
13 | }
14 |
15 | public int Spacing
16 | {
17 | get => (int)GetValue(SpacingProperty);
18 | set => SetValue(SpacingProperty, value);
19 | }
20 |
21 | public static readonly DependencyProperty SpacingProperty =
22 | DependencyProperty.Register("Spacing", typeof(int),
23 | typeof(PushIcon), new PropertyMetadata(default(int)));
24 | }
25 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/RecycleIcon.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/RecycleIcon.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Controls;
2 |
3 | ///
4 | /// Interaction logic for RecycleIcon.xaml
5 | ///
6 | public partial class RecycleIcon : UserControl
7 | {
8 | public RecycleIcon()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/UninstallIcon.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/Icons/UninstallIcon.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Controls;
2 |
3 | ///
4 | /// Interaction logic for UninstallIcon.xaml
5 | ///
6 | public partial class UninstallIcon : UserControl
7 | {
8 | public UninstallIcon()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/MaskedTextBox.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/PasteAndPullTooltip.xaml.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 |
3 | namespace ADB_Explorer.Controls;
4 |
5 | ///
6 | /// Interaction logic for PasteAndPullTooltip.xaml
7 | ///
8 | public partial class PasteAndPullTooltip : UserControl
9 | {
10 | public bool TempHide { get; set; } = false;
11 |
12 | public PasteAndPullTooltip()
13 | {
14 | InitializeComponent();
15 | }
16 |
17 | private void Button_Click(object sender, RoutedEventArgs e)
18 | {
19 | Data.Settings.HidePasteNamingInfo = PermanentHideCheckBox.IsChecked is true;
20 | Visibility = Visibility.Hidden;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/RenameTooltip.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Controls;
2 |
3 | ///
4 | /// Interaction logic for RenameTooltip.xaml
5 | ///
6 | public partial class RenameTooltip : UserControl
7 | {
8 | public RenameTooltip()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/ResetSettingsIcon.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/ResetSettingsIcon.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Controls;
2 |
3 | ///
4 | /// Interaction logic for ResetSettingsIcon.xaml
5 | ///
6 | public partial class ResetSettingsIcon : UserControl
7 | {
8 | public ResetSettingsIcon()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Controls/TransferIndicator.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Controls;
2 |
3 | ///
4 | /// Interaction logic for TransferIndicator.xaml
5 | ///
6 | public partial class TransferIndicator : UserControl
7 | {
8 | public TransferIndicator()
9 | {
10 | InitializeComponent();
11 | }
12 |
13 | public bool IsUpVisible
14 | {
15 | get => (bool)GetValue(IsUpVisibleProperty);
16 | set => SetValue(IsUpVisibleProperty, value);
17 | }
18 |
19 | public static readonly DependencyProperty IsUpVisibleProperty =
20 | DependencyProperty.Register("IsUpVisible", typeof(bool),
21 | typeof(TransferIndicator), new PropertyMetadata(null));
22 |
23 | public bool IsDownVisible
24 | {
25 | get => (bool)GetValue(IsDownVisibleProperty);
26 | set => SetValue(IsDownVisibleProperty, value);
27 | }
28 |
29 | public static readonly DependencyProperty IsDownVisibleProperty =
30 | DependencyProperty.Register("IsDownVisible", typeof(bool),
31 | typeof(TransferIndicator), new PropertyMetadata(null));
32 |
33 | public Visibility UpVisibility => IsUpVisible ? Visibility.Visible : Visibility.Collapsed;
34 |
35 | public Visibility DownVisibility => IsDownVisible ? Visibility.Visible : Visibility.Collapsed;
36 | }
37 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/CellConverter.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Converters;
2 |
3 | public class CellConverter
4 | {
5 | public static DataGridCell GetDataGridCell(DataGridCellInfo cellInfo)
6 | {
7 | var cellContent = cellInfo.Column?.GetCellContent(cellInfo.Item);
8 | if (cellContent != null)
9 | return (DataGridCell)cellContent.Parent;
10 |
11 | return null;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/CompletedStatsConverter.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.ViewModels;
2 |
3 | namespace ADB_Explorer.Converters;
4 |
5 | internal class CompletedStatsConverter : IValueConverter
6 | {
7 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
8 | {
9 | var result = "";
10 | if (value is not CompletedSyncProgressViewModel info)
11 | return result;
12 |
13 | if (string.IsNullOrEmpty(info.TotalSize))
14 | return result;
15 |
16 | result += info.TotalSize;
17 | if (string.IsNullOrEmpty(info.TotalTime))
18 | return result;
19 |
20 | result += $" in {info.TotalTime}";
21 |
22 | if (string.IsNullOrEmpty(info.AverageRateString))
23 | return result;
24 |
25 | result += $" ({info.AverageRateString})";
26 | return result;
27 | }
28 |
29 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
30 | {
31 | throw new NotImplementedException();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/ControlSize.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Converters;
2 |
3 | public static class ControlSize
4 | {
5 | ///
6 | /// Returns the length of a path button.
7 | ///
8 | ///
9 | ///
10 | public static double GetWidth(UIElement item)
11 | {
12 | item.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
13 | return item.DesiredSize.Width;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/DoubleEquals.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Converters;
2 |
3 | public class DoubleEquals : IValueConverter
4 | {
5 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
6 | {
7 | if (parameter is string paramString)
8 | {
9 | if (double.TryParse(paramString, out double result))
10 | {
11 | var val = double.Parse($"{value}");
12 |
13 | return val == result;
14 | }
15 | }
16 |
17 | return null;
18 | }
19 |
20 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
21 | {
22 | return null;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/EnumToBooleanConverter.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Converters;
2 |
3 | public class EnumToBooleanConverter : IValueConverter
4 | {
5 | public Type EnumType { get; set; }
6 |
7 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
8 | {
9 | if (parameter is string enumString)
10 | {
11 | if (Enum.IsDefined(EnumType, value))
12 | {
13 | var enumValue = Enum.Parse(EnumType, enumString);
14 |
15 | return enumValue.Equals(value);
16 | }
17 | }
18 |
19 | return false;
20 | }
21 |
22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
23 | {
24 | if (parameter is string enumString)
25 | {
26 | return Enum.Parse(EnumType, enumString);
27 | }
28 |
29 | return null;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/FileOpProgressConverter.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Converters;
2 |
3 | public class FileOpProgressConverter : IValueConverter
4 | {
5 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
6 | {
7 | return value switch
8 | {
9 | double val when val
10 | is double.NaN
11 | or double.PositiveInfinity
12 | or double.NegativeInfinity => 0.0,
13 | int or long or double => value,
14 | _ => 0.0
15 | };
16 | }
17 |
18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
19 | {
20 | return null;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/FileOpTreeStatusConverter.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Helpers;
2 | using ADB_Explorer.Models;
3 | using ADB_Explorer.Services;
4 | using static ADB_Explorer.Converters.FileOpStatusConverter;
5 |
6 | namespace ADB_Explorer.Converters;
7 |
8 | internal class FileOpTreeStatusConverter : IValueConverter
9 | {
10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | if (value is ObservableList children)
13 | {
14 | var (failed, type) = CountFails(children);
15 |
16 | return StatusString(type, children.Count - failed, failed);
17 | }
18 | else if (value is ObservableList updates)
19 | {
20 | return StatusString(updates.First().GetType(), message: updates.OfType().LastOrDefault()?.Message);
21 | }
22 |
23 | throw new NotSupportedException();
24 | }
25 |
26 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
27 | {
28 | throw new NotImplementedException();
29 | }
30 | }
31 |
32 | public static class FileOpStatusConverter
33 | {
34 | public static string StatusString(Type type, int completed = 0, int failed = -1, string message = "", bool total = false)
35 | {
36 | if (!string.IsNullOrEmpty(message))
37 | {
38 | return message.StartsWith(Strings.Resources.S_REDIRECTION)
39 | ? message
40 | : string.Format(Strings.Resources.S_FILEOP_ERROR, message);
41 | }
42 |
43 | var completedString = (type == typeof(HashFailInfo) || type == typeof(HashSuccessInfo))
44 | ? Strings.Resources.S_FILEOP_VALIDATED
45 | : Strings.Resources.S_FILEOP_COMPLETED;
46 |
47 | if (failed == -1)
48 | return completedString;
49 |
50 | if (type == typeof(ShellErrorInfo))
51 | return $"({string.Format(Strings.Resources.S_FILEOP_SUBITEM_FAILED, failed)})";
52 |
53 | var failedString = failed > 0 ? $"{string.Format(Strings.Resources.S_FILEOP_SUBITEM_FAILED, failed)}, " : "";
54 |
55 | return $"({(total ? $"{Strings.Resources.S_FILEOP_TOTAL} " : "")}{failedString}{completed} {completedString})";
56 | }
57 |
58 | public static (int, Type) CountFails(ObservableList children)
59 | {
60 | int total = 0;
61 |
62 | foreach (var item in children.Where(c => c.Children.Count > 0))
63 | {
64 | if (CountFails(item.Children).Item1 > 0)
65 | total++;
66 | }
67 |
68 | total += children.Count(c => c.Children.Count == 0 && c.ProgressUpdates.OfType().Any());
69 |
70 | var type = typeof(SyncErrorInfo);
71 | if (children.Any(c => c.ProgressUpdates.Any(u => u is ShellErrorInfo)))
72 | type = typeof(ShellErrorInfo);
73 | else if (children.Any(c => c.ProgressUpdates.Any(u => u is HashFailInfo or HashSuccessInfo)))
74 | type = typeof(HashFailInfo);
75 |
76 | return (total, type);
77 | }
78 | }
--------------------------------------------------------------------------------
/ADB Explorer/Converters/MarginConverter.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Converters;
2 |
3 | public class MarginConverter : IMultiValueConverter
4 | {
5 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
6 | {
7 | // arg 0 - ExpansionProgress
8 | // arg 1 - ExpandDirection
9 | // arg 2 - ContentHeight
10 | // arg 3 - ContentWidth
11 |
12 | if (values.Length < 4)
13 | throw new ArgumentException("This function requires 4 arguments.");
14 | else if (values[0] is not double || values[1] is not ExpandDirection || values[2] is not double || values[3] is not double)
15 | throw new ArgumentException("Provided arguments are not of correct format.");
16 |
17 | var expansionProgress = (double)values[0];
18 | var expandDirection = (ExpandDirection)values[1];
19 | var contentHeight = (double)values[2];
20 | var contentWidth = (double)values[3];
21 |
22 | var size = expandDirection switch
23 | {
24 | ExpandDirection.Down or ExpandDirection.Up => contentHeight,
25 | ExpandDirection.Left or ExpandDirection.Right => contentWidth,
26 | _ => throw new NotSupportedException(),
27 | };
28 |
29 | var result = -size * (1 - expansionProgress);
30 |
31 | return expandDirection switch
32 | {
33 | ExpandDirection.Down => new Thickness(0, result, 0, 0),
34 | ExpandDirection.Up => new Thickness(0, 0, 0, result),
35 | ExpandDirection.Left => new Thickness(0, 0, result, 0),
36 | ExpandDirection.Right => new Thickness(result, 0, 0, 0),
37 | _ => throw new NotSupportedException(),
38 | };
39 | }
40 |
41 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
42 | {
43 | throw new NotImplementedException();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/MenuItemConverter.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Converters;
2 |
3 | class MenuItemConverter : IValueConverter
4 | {
5 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
6 | {
7 | DependencyObject parent = value as UIElement;
8 | while (parent is not null and not Menu)
9 | parent = VisualTreeHelper.GetParent(parent);
10 |
11 | if (parent is null)
12 | return null;
13 |
14 | return parameter switch
15 | {
16 | "Padding" => Helpers.MenuHelper.GetItemPadding(parent as UIElement),
17 | "Margin" => Helpers.MenuHelper.GetItemMargin(parent as UIElement),
18 | "Style" => Helpers.MenuHelper.GetIsButtonMenu(parent as UIElement),
19 | _ => throw new NotSupportedException(),
20 | };
21 | }
22 |
23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
24 | {
25 | throw new NotSupportedException();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/SizeConverter.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Converters
2 | {
3 | public static class UnitConverter
4 | {
5 | private static readonly Dictionary scale_table = new() { { -3, "n" }, { -2, "u" }, { -1, "m" }, { 0, "" }, { 1, "K" }, { 2, "M" }, { 3, "G" }, { 4, "T" }, { 5, "P" }, { 6, "E" } };
6 |
7 | public static string ToSize(this UInt64 bytes, bool scaleSpace = false, int bigRound = 1, int smallRound = 0)
8 | {
9 | int scale = (bytes == 0) ? 0 : Convert.ToInt32(Math.Floor(Math.Round(Math.Log(bytes, 1024), 2))); // 0 <= scale <= 6
10 | double value = bytes / Math.Pow(1024, scale);
11 | return $"{(Math.Round(value, value < 100 ? bigRound : smallRound))}{(scaleSpace ? " " : "")}{scale_table[scale]}B";
12 | }
13 |
14 | public static string ToSize(this double source, bool scaleSpace = false, int bigRound = 1, int smallRound = 0)
15 | {
16 | int scale = (source == 0) ? 0 : Convert.ToInt32(Math.Floor(Math.Round(Math.Log(Math.Abs(source), 1000), 2)));
17 | double value = source / Math.Pow(1000, scale);
18 | return $"{(Math.Round(value, value < 100 ? bigRound : smallRound))}{(scaleSpace ? " " : "")}{scale_table[scale]}";
19 | }
20 |
21 | public static string ToTime(this decimal? seconds, bool scaleSpace = false, bool useMilli = true, int digits = 2)
22 | {
23 | if (seconds is null)
24 | return "";
25 |
26 | TimeSpan span = TimeSpan.FromSeconds((double)seconds);
27 | string resolution;
28 | string value;
29 |
30 | if (span.Days == 0)
31 | {
32 | if (span.Hours == 0)
33 | {
34 | if (span.Minutes == 0)
35 | {
36 | if (useMilli && span.Seconds == 0)
37 | {
38 | value = $"{Math.Round(span.TotalMilliseconds, span.TotalMilliseconds < 100 ? digits : 1)}";
39 | resolution = Strings.Resources.S_MILLISECONDS_SHORT;
40 | }
41 | else
42 | {
43 | value = $"{Math.Round(span.TotalSeconds, digits)}";
44 | resolution = Strings.Resources.S_SECONDS_SHORT;
45 | }
46 | }
47 | else
48 | {
49 | value = $"{span.Minutes}:{span.Seconds:00}";
50 | resolution = Strings.Resources.S_MINUTES_SHORT;
51 | }
52 | }
53 | else
54 | {
55 | value = $"{span.Hours}:{span.Minutes:00}:{span.Seconds:00}";
56 | resolution = Strings.Resources.S_HOURS_SHORT;
57 | }
58 | }
59 | else
60 | {
61 | value = $"{Math.Round(span.TotalHours)}";
62 | resolution = Strings.Resources.S_HOURS_SHORT;
63 | }
64 |
65 | return string.Format(resolution, $"{value}{(scaleSpace ? " " : "")}");
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/StringFormatConverter.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Converters;
2 |
3 | public class StringFormatConverter : IMultiValueConverter
4 | {
5 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
6 | {
7 | if (parameter is not string format)
8 | return string.Empty;
9 |
10 | try
11 | {
12 | return string.Format(format, values);
13 | }
14 | catch
15 | {
16 | return format;
17 | }
18 | }
19 |
20 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
21 | {
22 | throw new NotSupportedException();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/TreeViewIndentConverter.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Converters;
2 |
3 | internal class TreeViewIndentConverter : IValueConverter
4 | {
5 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
6 | {
7 | if (value is Thickness margin)
8 | return new Thickness(-1 * margin.Left, margin.Top, margin.Right, margin.Bottom);
9 |
10 | return null;
11 | }
12 |
13 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
14 | {
15 | throw new NotImplementedException();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ADB Explorer/Converters/TrimmedTooltipConverter.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Converters;
2 |
3 | public class TrimmedTooltipConverter : IValueConverter
4 | {
5 |
6 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
7 | {
8 | if (value is null)
9 | return Visibility.Collapsed;
10 |
11 | // FrameworkElement to include both TextBlock and TextBox
12 | var textBlock = value as FrameworkElement;
13 |
14 | textBlock.Measure(new(double.PositiveInfinity, double.PositiveInfinity));
15 | var margin = textBlock.Margin.Left + textBlock.Margin.Right;
16 |
17 | return textBlock.ActualWidth + margin < textBlock.DesiredSize.Width
18 | ? Visibility.Visible
19 | : Visibility.Collapsed;
20 | }
21 |
22 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
23 | {
24 | throw new NotImplementedException();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/AppInfra/AsyncHelper.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Helpers;
2 |
3 | public static class AsyncHelper
4 | {
5 | public static async Task WaitUntil(Func condition, TimeSpan timeout, TimeSpan assertDelay, CancellationToken cancellationToken)
6 | {
7 | var waitTask = Task.Run(async () =>
8 | {
9 | while (!condition()) await Task.Delay(assertDelay, cancellationToken);
10 | }, cancellationToken);
11 |
12 | await Task.WhenAny(waitTask, Task.Delay(timeout, cancellationToken));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/AppInfra/ByteHelper.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Helpers;
2 |
3 | public class ByteHelper
4 | {
5 | public static int PatternAt(byte[] source, byte[] pattern, int startIndex = 0, bool evenAlign = false)
6 | {
7 | for (int i = startIndex; i < source.Length; i++)
8 | {
9 | if (source.Skip(i).Take(pattern.Length).SequenceEqual(pattern)
10 | && (int.IsEvenInteger(i) || !evenAlign))
11 | {
12 | return i;
13 | }
14 | }
15 |
16 | return -1;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/AppInfra/CommandHandler.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.ViewModels;
2 |
3 | namespace ADB_Explorer.Helpers;
4 |
5 | public class CommandHandler : ICommand
6 | {
7 | private readonly Action _action;
8 | private readonly Func _canExecute;
9 |
10 | ///
11 | /// Raises an event when the command is executed.
12 | ///
13 | public ObservableProperty OnExecute { get; set; } = new();
14 |
15 | public void Execute(object parameter)
16 | {
17 | _action();
18 |
19 | OnExecute.Value ^= true;
20 | }
21 |
22 | public bool CanExecute(object parameter)
23 | {
24 | return _canExecute.Invoke();
25 | }
26 |
27 | public CommandHandler(Action action, Func canExecute)
28 | {
29 | _action = action;
30 | _canExecute = canExecute;
31 | }
32 |
33 | public event EventHandler CanExecuteChanged
34 | {
35 | add => CommandManager.RequerySuggested += value;
36 | remove => CommandManager.RequerySuggested -= value;
37 | }
38 |
39 | }
40 |
41 | public class BaseAction : ViewModelBase
42 | {
43 | private readonly Func canExecute;
44 | public bool IsEnabled => canExecute();
45 |
46 | private readonly Action action;
47 |
48 | private ICommand command;
49 | public ICommand Command => command ??= new CommandHandler(action, canExecute);
50 |
51 | public BaseAction(Func canExecute, Action action)
52 | {
53 | this.canExecute = canExecute ??= () => true;
54 | this.action = action;
55 | }
56 |
57 | public BaseAction()
58 | {
59 | canExecute = () => true;
60 | action = () => { };
61 | }
62 |
63 | public void Execute() => Command.Execute(null);
64 | }
65 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/AppInfra/DictionaryHelper.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Helpers;
2 |
3 | public static class DictionaryHelper
4 | {
5 | public static Dictionary TryToDictionary(this IEnumerable source, Func keySelector, Func elementSelector) where TKey : notnull =>
6 | TryToDictionary(source, keySelector, elementSelector, null);
7 |
8 | public static Dictionary TryToDictionary(this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer? comparer) where TKey : notnull
9 | {
10 | ArgumentNullException.ThrowIfNull(source);
11 |
12 | ArgumentNullException.ThrowIfNull(keySelector);
13 |
14 | ArgumentNullException.ThrowIfNull(elementSelector);
15 |
16 | int capacity = 0;
17 | if (source is ICollection collection)
18 | {
19 | capacity = collection.Count;
20 | if (capacity == 0)
21 | {
22 | return new Dictionary(comparer);
23 | }
24 |
25 | if (collection is TSource[] array)
26 | {
27 | return TryToDictionary(array, keySelector, elementSelector, comparer);
28 | }
29 |
30 | if (collection is List list)
31 | {
32 | return TryToDictionary(list, keySelector, elementSelector, comparer);
33 | }
34 | }
35 |
36 | Dictionary d = new Dictionary(capacity, comparer);
37 | foreach (TSource element in source)
38 | {
39 | d.TryAdd(keySelector(element), elementSelector(element));
40 | }
41 |
42 | return d;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/AppInfra/ListHelper.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Helpers;
2 |
3 | internal static class ListHelper
4 | {
5 | public static ListSortDirection Invert(ListSortDirection? value)
6 | {
7 | return value is ListSortDirection and ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending;
8 | }
9 |
10 | ///
11 | /// Appends an IEnumerable to the end of another IEnumerable.
12 | /// *** ENUMERATES BOTH OF THE ENUMERABLES ***
13 | ///
14 | public static IEnumerable AppendRange(this IEnumerable self, IEnumerable other)
15 | {
16 | foreach (var item in self)
17 | {
18 | yield return item;
19 | }
20 |
21 | foreach (var item in other)
22 | {
23 | yield return item;
24 | }
25 | }
26 |
27 | ///
28 | /// Determines whether all elements of a sequence satisfy a condition
29 | ///
30 | /// if the source sequence contains any elements and every element passes the test in the specified predicate; otherwise,
31 | public static bool AnyAll(this IEnumerable source, Func predicate)
32 | {
33 | return source.Any() && source.All(predicate);
34 | }
35 |
36 | ///
37 | /// Performs the specified on each element of the collection
38 | ///
39 | public static void ForEach(this IEnumerable self, Action action)
40 | {
41 | foreach (var item in self)
42 | {
43 | action(item);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/AppInfra/ObservableProperty.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Helpers;
2 |
3 | public class PropertyChangedEventArgs : EventArgs
4 | {
5 | public T OldValue { get; set; }
6 | public T NewValue { get; set; }
7 | }
8 |
9 | public class ObservableProperty
10 | {
11 | public event EventHandler> PropertyChanged;
12 |
13 | private T _value;
14 | public T Value
15 | {
16 | get => _value;
17 | set
18 | {
19 | if (Equals(_value, value))
20 | return;
21 |
22 | PropertyChangedEventArgs args = new()
23 | {
24 | OldValue = _value,
25 | NewValue = value
26 | };
27 |
28 | _value = value;
29 | PropertyChanged?.Invoke(this, args);
30 | }
31 | }
32 |
33 | public static implicit operator T(ObservableProperty p) => p.Value;
34 | }
35 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/AppInfra/RandomString.cs:
--------------------------------------------------------------------------------
1 | using static ADB_Explorer.Models.AdbExplorerConst;
2 |
3 | namespace ADB_Explorer.Helpers;
4 |
5 | public class RandomString
6 | {
7 | public static string GetUniqueKey(int size, char[] chars = null)
8 | {
9 | if (chars is null)
10 | {
11 | chars = WIFI_PAIRING_ALPHABET;
12 | }
13 |
14 | byte[] data = new byte[4 * size];
15 | RandomNumberGenerator.Create().GetBytes(data);
16 |
17 | StringBuilder result = new();
18 | for (int i = 0; i < size; i++)
19 | {
20 | var rnd = BitConverter.ToUInt32(data, i * 4);
21 | var idx = rnd % chars.Length;
22 |
23 | result.Append(chars[idx]);
24 | }
25 |
26 | return result.ToString();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/Attachable/DialogHelper.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Helpers;
2 |
3 | public static class DialogHelper
4 | {
5 | public static string GetDialogIcon(ContentDialog control) =>
6 | (string)control.GetValue(DialogIconProperty);
7 |
8 | public static void SetDialogIcon(ContentDialog control, string value) =>
9 | control.SetValue(DialogIconProperty, value);
10 |
11 | public static readonly DependencyProperty DialogIconProperty =
12 | DependencyProperty.RegisterAttached(
13 | "DialogIcon",
14 | typeof(string),
15 | typeof(DialogHelper),
16 | null);
17 | }
18 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/Attachable/MenuHelper.cs:
--------------------------------------------------------------------------------
1 | using Windows.UI.Popups;
2 |
3 | namespace ADB_Explorer.Helpers;
4 |
5 | public static class MenuHelper
6 | {
7 | public static bool GetIsMouseSelectionVisible(UIElement control) =>
8 | (bool)control.GetValue(IsMouseSelectionVisibleProperty);
9 |
10 | public static void SetIsMouseSelectionVisible(UIElement control, bool value) =>
11 | control.SetValue(IsMouseSelectionVisibleProperty, value);
12 |
13 | public static readonly DependencyProperty IsMouseSelectionVisibleProperty =
14 | DependencyProperty.RegisterAttached(
15 | "IsMouseSelectionVisible",
16 | typeof(bool),
17 | typeof(MenuHelper),
18 | null);
19 |
20 | public static Brush GetCheckBackground(UIElement control) =>
21 | (Brush)control.GetValue(CheckBackgroundProperty);
22 |
23 | public static void SetCheckBackground(UIElement control, Brush value) =>
24 | control.SetValue(CheckBackgroundProperty, value);
25 |
26 | public static readonly DependencyProperty CheckBackgroundProperty =
27 | DependencyProperty.RegisterAttached(
28 | "CheckBackground",
29 | typeof(Brush),
30 | typeof(MenuHelper),
31 | null);
32 |
33 | public static Thickness GetItemPadding(UIElement control) =>
34 | (Thickness)control.GetValue(ItemPaddingProperty);
35 |
36 | public static void SetItemPadding(UIElement control, Thickness value) =>
37 | control.SetValue(ItemPaddingProperty, value);
38 |
39 | public static readonly DependencyProperty ItemPaddingProperty =
40 | DependencyProperty.RegisterAttached(
41 | "ItemPadding",
42 | typeof(Thickness),
43 | typeof(MenuHelper),
44 | null);
45 |
46 | public static Thickness GetItemMargin(UIElement control) =>
47 | (Thickness)control.GetValue(ItemMarginProperty);
48 |
49 | public static void SetItemMargin(UIElement control, Thickness value) =>
50 | control.SetValue(ItemMarginProperty, value);
51 |
52 | public static readonly DependencyProperty ItemMarginProperty =
53 | DependencyProperty.RegisterAttached(
54 | "ItemMargin",
55 | typeof(Thickness),
56 | typeof(MenuHelper),
57 | null);
58 |
59 | public static bool? GetIsButtonMenu(UIElement control) =>
60 | (bool?)control.GetValue(IsButtonMenuProperty);
61 |
62 | public static void SetIsButtonMenu(UIElement control, bool? value) =>
63 | control.SetValue(IsButtonMenuProperty, value);
64 |
65 | public static readonly DependencyProperty IsButtonMenuProperty =
66 | DependencyProperty.RegisterAttached(
67 | "IsButtonMenu",
68 | typeof(bool?),
69 | typeof(MenuHelper),
70 | null);
71 |
72 | public static PlacementMode GetDropDownPlacement(UIElement control) =>
73 | (PlacementMode)control.GetValue(DropDownPlacementProperty);
74 |
75 | public static void SetDropDownPlacement(UIElement control, PlacementMode value) =>
76 | control.SetValue(DropDownPlacementProperty, value);
77 |
78 | public static readonly DependencyProperty DropDownPlacementProperty =
79 | DependencyProperty.RegisterAttached(
80 | "DropDownPlacement",
81 | typeof(PlacementMode),
82 | typeof(MenuHelper),
83 | null);
84 | }
85 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/Attachable/VisibilityHelper.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Helpers;
2 |
3 | public static class VisibilityHelper
4 | {
5 | public static Visibility Visible(bool? value) => value is bool and true ? Visibility.Visible : Visibility.Collapsed;
6 |
7 | public static void Visible(this FrameworkElement control, bool value) => control.Visibility = Visible(value);
8 |
9 | public static bool Visible(this FrameworkElement control) => control.Visibility == Visibility.Visible;
10 |
11 | public static void ToggleVisibility(this FrameworkElement control) => control.Visible(!control.Visible());
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/DriveHelper.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 | using ADB_Explorer.ViewModels;
3 |
4 | namespace ADB_Explorer.Helpers;
5 |
6 | internal class DriveHelper
7 | {
8 | public static void ClearSelectedDrives()
9 | {
10 | Data.RuntimeSettings.CollapseDrives = true;
11 | Data.RuntimeSettings.CollapseDrives = false;
12 | }
13 |
14 | public static void ClearDrives()
15 | {
16 | Data.DevicesObject.Current?.Drives.Clear();
17 | Data.FileActions.IsDriveViewVisible = false;
18 | }
19 |
20 | public static DriveViewModel GetCurrentDrive(string path)
21 | {
22 | if (string.IsNullOrEmpty(path)) return null;
23 |
24 | // First search for a non-root drive that matches the path
25 | var nonRoot = Data.DevicesObject.Current?.Drives.FirstOrDefault(d => d.Type is not AbstractDrive.DriveType.Root && path.StartsWith(d.Path));
26 | if (nonRoot is null)
27 | return Data.DevicesObject.Current?.Drives.FirstOrDefault(d => d.Type is AbstractDrive.DriveType.Root);
28 |
29 | return nonRoot;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/File/FolderHelper.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 | using ADB_Explorer.Services;
3 | using ADB_Explorer.ViewModels;
4 |
5 | namespace ADB_Explorer.Helpers;
6 |
7 | public class FolderHelper
8 | {
9 | public static void CombineDisplayNames()
10 | {
11 | var driveView = NavHistory.StringFromLocation(NavHistory.SpecialLocation.DriveView);
12 | if (Data.CurrentDisplayNames.ContainsKey(driveView))
13 | Data.CurrentDisplayNames[driveView] = Data.DevicesObject.Current.Name;
14 | else
15 | Data.CurrentDisplayNames.Add(driveView, Data.DevicesObject.Current.Name);
16 |
17 | foreach (var drive in Data.DevicesObject.Current.Drives.OfType().Where(d => d.Type
18 | is not AbstractDrive.DriveType.Root
19 | and not AbstractDrive.DriveType.Internal))
20 | {
21 | Data.CurrentDisplayNames.TryAdd(drive.Path, drive.Type is AbstractDrive.DriveType.External
22 | ? drive.ID : drive.DisplayName);
23 | }
24 |
25 | foreach (var item in AdbExplorerConst.DRIVE_TYPES.Where(d => d.Value is AbstractDrive.DriveType.Root or AbstractDrive.DriveType.Internal))
26 | {
27 | Data.CurrentDisplayNames.TryAdd(item.Key, AbstractDrive.GetDriveDisplayName(item.Value));
28 | }
29 |
30 | foreach (var item in AdbExplorerConst.DRIVE_TYPES)
31 | {
32 | var names = Enum.GetValues().Where(n => n == item.Value && item.Value
33 | is not AbstractDrive.DriveType.Root
34 | and not AbstractDrive.DriveType.Internal)
35 | .Select(AbstractDrive.GetDriveDisplayName);
36 |
37 | if (names.Any())
38 | Data.CurrentDisplayNames.TryAdd(item.Key, names.First());
39 | }
40 |
41 | Data.RuntimeSettings.RefreshBreadcrumbs = true;
42 | }
43 |
44 | public static string FolderExists(string path)
45 | {
46 | if (path == NavHistory.StringFromLocation(NavHistory.SpecialLocation.PackageDrive))
47 | return path;
48 |
49 | if (path == NavHistory.StringFromLocation(NavHistory.SpecialLocation.RecycleBin))
50 | return AdbExplorerConst.RECYCLE_PATH;
51 |
52 | try
53 | {
54 | return Data.CurrentADBDevice.TranslateDevicePath(path);
55 | }
56 | catch (Exception e)
57 | {
58 | if (path != AdbExplorerConst.RECYCLE_PATH)
59 | DialogService.ShowMessage(e.Message, Strings.Resources.S_NAV_ERR_TITLE, DialogService.DialogIcon.Critical, copyToClipboard: true);
60 |
61 | return null;
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/File/TrashHelper.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 | using ADB_Explorer.Services;
3 | using ADB_Explorer.ViewModels;
4 |
5 | namespace ADB_Explorer.Helpers;
6 |
7 | internal static class TrashHelper
8 | {
9 | public static void EnableRecycleButtons(IEnumerable fileList = null)
10 | {
11 | if (fileList is null)
12 | fileList = Data.DirList.FileList;
13 |
14 | Data.FileActions.RestoreEnabled = fileList.Any(file => file.TrashIndex is not null && !string.IsNullOrEmpty(file.TrashIndex.OriginalPath));
15 | Data.FileActions.DeleteEnabled = fileList.Any(item => item.Extension != AdbExplorerConst.RECYCLE_INDEX_SUFFIX);
16 | }
17 |
18 | public static void UpdateRecycledItemsCount()
19 | {
20 | var countTask = Task.Run(() => ADBService.CountRecycle(Data.DevicesObject.Current.ID));
21 | countTask.ContinueWith((t) =>
22 | {
23 | if (t.IsCanceled || Data.DevicesObject.Current is null)
24 | return;
25 |
26 | var count = t.Result;
27 | if (count < 1)
28 | count = FolderHelper.FolderExists(AdbExplorerConst.RECYCLE_PATH) is null ? -1 : 0;
29 |
30 | var trash = Data.DevicesObject.Current?.Drives.Find(d => d.Type is AbstractDrive.DriveType.Trash);
31 | App.Current.Dispatcher.Invoke(() => ((VirtualDriveViewModel)trash)?.SetItemsCount(count));
32 | });
33 | }
34 |
35 | public static Task ParseIndexersAsync() => Task.Run(() =>
36 | {
37 | Data.RecycleIndex.Clear();
38 |
39 | var indexers = ADBService.FindFilesInPath(Data.CurrentADBDevice.ID,
40 | AdbExplorerConst.RECYCLE_PATH,
41 | includeNames: ["*" + AdbExplorerConst.RECYCLE_INDEX_SUFFIX]);
42 |
43 | var lines = ShellFileOperation.ReadAllText(Data.CurrentADBDevice, indexers).Split(ADBService.LINE_SEPARATORS,
44 | StringSplitOptions.RemoveEmptyEntries);
45 |
46 | lines.ToList().ForEach(line => Data.RecycleIndex.Add(new(line)));
47 | });
48 |
49 | public static void ParseIndexers()
50 | {
51 | Data.RecycleIndex.Clear();
52 |
53 | var indexers = ADBService.FindFilesInPath(Data.CurrentADBDevice.ID,
54 | AdbExplorerConst.RECYCLE_PATH,
55 | includeNames: ["*" + AdbExplorerConst.RECYCLE_INDEX_SUFFIX]);
56 |
57 | var lines = ShellFileOperation.ReadAllText(Data.CurrentADBDevice, indexers).Split(ADBService.LINE_SEPARATORS,
58 | StringSplitOptions.RemoveEmptyEntries);
59 |
60 | lines.ToList().ForEach(line => Data.RecycleIndex.Add(new(line)));
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/FileOp/FinishedTestOperation.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 | using ADB_Explorer.Services;
3 | using ADB_Explorer.ViewModels;
4 |
5 | namespace ADB_Explorer.Helpers;
6 |
7 | public class CompletedTestOperation : FileOperation
8 | {
9 | private readonly CompletedSyncProgressViewModel info;
10 |
11 | public override SyncFile AndroidPath => TargetPath;
12 |
13 | public CompletedTestOperation(Dispatcher dispatcher, ADBService.AdbDevice adbDevice, SyncFile filePath, AdbSyncStatsInfo adbInfo) :
14 | base(filePath, adbDevice, dispatcher)
15 | {
16 | info = new(adbInfo);
17 | TargetPath = filePath;
18 | }
19 |
20 | public static CompletedTestOperation CreateFileCompleted(Dispatcher dispatcher, ADBService.AdbDevice adbDevice, string filePath)
21 | => new(dispatcher, adbDevice, new(filePath), new(filePath, 1, 0, 2.3m, 3141592653589, 123));
22 |
23 | public static CompletedTestOperation CreateFolderCompleted(Dispatcher dispatcher, ADBService.AdbDevice adbDevice, string folderPath)
24 | => new(
25 | dispatcher,
26 | adbDevice,
27 | new(folderPath, AbstractFile.FileType.Folder),
28 | new(folderPath, 10, 0, 2.3m, 3141592653589, 123));
29 |
30 | public static CompletedTestOperation CreateFileSkipped(Dispatcher dispatcher, ADBService.AdbDevice adbDevice, string filePath)
31 | => new(dispatcher, adbDevice, new(filePath), new(filePath, 0, 1, 0m, 0, 0));
32 |
33 | public static CompletedTestOperation CreateFolderPartiallySkipped(Dispatcher dispatcher, ADBService.AdbDevice adbDevice, string folderPath)
34 | => new(dispatcher, adbDevice, new(folderPath, AbstractFile.FileType.Folder), new(folderPath, 7, 3, 2.3m, 3141592653589, 123));
35 |
36 | public override void Start()
37 | {
38 | Status = OperationStatus.Completed;
39 | StatusInfo = info;
40 | }
41 |
42 | public override void Cancel()
43 | {
44 | Status = OperationStatus.Canceled;
45 | StatusInfo = new CanceledOpProgressViewModel();
46 | }
47 |
48 | public override void ClearChildren()
49 | => TargetPath.Children.Clear();
50 |
51 | public override void AddUpdates(IEnumerable newUpdates)
52 | => TargetPath.AddUpdates(newUpdates);
53 |
54 | public override void AddUpdates(params FileOpProgressInfo[] newUpdates)
55 | => TargetPath.AddUpdates(newUpdates);
56 | }
57 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/FileOp/InProgressTestOperation.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 | using ADB_Explorer.Services;
3 | using ADB_Explorer.ViewModels;
4 |
5 | namespace ADB_Explorer.Helpers;
6 |
7 | public class InProgressTestOperation : FileOperation
8 | {
9 | private readonly InProgSyncProgressViewModel info;
10 |
11 | public override SyncFile FilePath { get; }
12 |
13 | public override SyncFile AndroidPath => FilePath;
14 |
15 | private InProgressTestOperation(Dispatcher dispatcher, ADBService.AdbDevice adbDevice, string filePath, AdbSyncProgressInfo adbInfo) :
16 | base(new(filePath), adbDevice, dispatcher)
17 | {
18 | info = new(adbInfo);
19 | FilePath = new SyncFile(filePath, adbInfo.CurrentFilePercentage.HasValue ? AbstractFile.FileType.Folder : AbstractFile.FileType.File);
20 | }
21 |
22 | public static InProgressTestOperation CreateProgressStart(Dispatcher dispatcher, ADBService.AdbDevice adbDevice, string filePath)
23 | {
24 | return new InProgressTestOperation(dispatcher, adbDevice, filePath, new AdbSyncProgressInfo(null, null, null, null));
25 | }
26 |
27 | public static InProgressTestOperation CreateFileInProgress(Dispatcher dispatcher, ADBService.AdbDevice adbDevice, string filePath)
28 | {
29 | return new InProgressTestOperation(dispatcher, adbDevice, filePath, new AdbSyncProgressInfo(null, 40, null, null));
30 | }
31 |
32 | public static InProgressTestOperation CreateFolderInProgress(Dispatcher dispatcher, ADBService.AdbDevice adbDevice, string filePath)
33 | {
34 | return new InProgressTestOperation(dispatcher, adbDevice, filePath, new AdbSyncProgressInfo("Subfile.txt", 40, 60, null));
35 | }
36 |
37 | public override void Start()
38 | {
39 | Status = OperationStatus.InProgress;
40 | StatusInfo = info;
41 | }
42 |
43 | public override void Cancel()
44 | {
45 | Status = OperationStatus.Canceled;
46 | StatusInfo = new CanceledOpProgressViewModel();
47 | }
48 |
49 | public void Fail(string errorMsg)
50 | {
51 | Status = OperationStatus.Failed;
52 | StatusInfo = new FailedOpProgressViewModel(errorMsg);
53 | }
54 |
55 | public void UpdateStatus(FileOpProgressInfo update)
56 | {
57 | if (update is SyncErrorInfo)
58 | return;
59 |
60 | StatusInfo = new InProgSyncProgressViewModel((AdbSyncProgressInfo)update);
61 | }
62 |
63 | public override void ClearChildren()
64 | {
65 | AndroidPath.Children.Clear();
66 | AndroidPath.ProgressUpdates.Clear();
67 | }
68 |
69 | public override void AddUpdates(IEnumerable newUpdates)
70 | => AndroidPath.AddUpdates(newUpdates);
71 |
72 | public override void AddUpdates(params FileOpProgressInfo[] newUpdates)
73 | => AndroidPath.AddUpdates(newUpdates);
74 | }
75 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/QrGenerator.cs:
--------------------------------------------------------------------------------
1 | using QRCoder;
2 | using QRCoder.Xaml;
3 |
4 | namespace ADB_Explorer.Helpers;
5 |
6 | public static class QrGenerator
7 | {
8 | public static DrawingImage GenerateQR(string val, SolidColorBrush background, SolidColorBrush foreground)
9 | {
10 | QRCodeGenerator qrGenerator = new QRCodeGenerator();
11 | QRCodeData qrCodeData = qrGenerator.CreateQrCode(val, QRCodeGenerator.ECCLevel.Q);
12 | var qrCode = new XamlQRCode(qrCodeData);
13 | var image = qrCode.GetGraphic(new System.Windows.Size(256, 256), foreground, background, false);
14 |
15 | return image;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/TemplateSelectors/DeviceTemplateSelector.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.ViewModels;
2 |
3 | namespace ADB_Explorer.Helpers;
4 |
5 | public class DeviceTemplateSelector : DataTemplateSelector
6 | {
7 | public DataTemplate LogicalDeviceTemplate { get; set; }
8 | public DataTemplate ServiceDeviceTemplate { get; set; }
9 | public DataTemplate NewDeviceTemplate { get; set; }
10 | public DataTemplate HistoryDeviceTemplate { get; set; }
11 | public DataTemplate WsaPkgDeviceTemplate { get; set; }
12 |
13 | public override DataTemplate SelectTemplate(object item, DependencyObject container) => item switch
14 | {
15 | LogicalDeviceViewModel => LogicalDeviceTemplate,
16 | ServiceDeviceViewModel => ServiceDeviceTemplate,
17 | HistoryDeviceViewModel => HistoryDeviceTemplate,
18 | NewDeviceViewModel => NewDeviceTemplate,
19 | WsaPkgDeviceViewModel => WsaPkgDeviceTemplate,
20 | _ => throw new NotImplementedException(),
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/TemplateSelectors/DriveTemplateSelector.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.ViewModels;
2 |
3 | namespace ADB_Explorer.Helpers;
4 |
5 | public class DriveTemplateSelector : DataTemplateSelector
6 | {
7 | public DataTemplate LogicalDriveTemplate { get; set; }
8 | public DataTemplate VirtualDriveTemplate { get; set; }
9 |
10 | public override DataTemplate SelectTemplate(object item, DependencyObject container) => item switch
11 | {
12 | LogicalDriveViewModel => LogicalDriveTemplate,
13 | VirtualDriveViewModel => VirtualDriveTemplate,
14 | _ => throw new NotImplementedException(),
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/TemplateSelectors/FileOpFileNameTemplateSelector.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Services;
2 |
3 | namespace ADB_Explorer.Helpers;
4 |
5 | internal class FileOpFileNameTemplateSelector : DataTemplateSelector
6 | {
7 | public DataTemplate UninstallOpFileNameTemplate { get; set; }
8 | public DataTemplate FolderCompletedOpFileNameTemplate { get; set; }
9 | public DataTemplate FolderInProgOpFileNameTemplate { get; set; }
10 | public DataTemplate RegularOpFileNameTemplate { get; set; }
11 |
12 | public override DataTemplate SelectTemplate(object item, DependencyObject container)
13 | {
14 | if (item is not FileOperation fileop)
15 | return null;
16 |
17 | if (fileop is PackageInstallOperation pkgInstall && pkgInstall.IsUninstall)
18 | return UninstallOpFileNameTemplate;
19 |
20 | if (fileop.FilePath.IsDirectory)
21 | return fileop.Status is FileOperation.OperationStatus.InProgress ? FolderInProgOpFileNameTemplate : FolderCompletedOpFileNameTemplate;
22 |
23 | return RegularOpFileNameTemplate;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/TemplateSelectors/FileOpProgressTemplateSelector.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.ViewModels;
2 |
3 | namespace ADB_Explorer.Helpers;
4 |
5 | internal class FileOpProgressTemplateSelector : DataTemplateSelector
6 | {
7 | public DataTemplate WaitingOpProgressTemplate { get; set; }
8 | public DataTemplate InProgSyncProgressTemplate { get; set; }
9 | public DataTemplate InProgShellProgressTemplate { get; set; }
10 | public DataTemplate CompletedSyncProgressTemplate { get; set; }
11 | public DataTemplate CompletedShellProgressTemplate { get; set; }
12 | public DataTemplate CanceledOpProgressTemplate { get; set; }
13 | public DataTemplate FailedOpProgressTemplate { get; set; }
14 |
15 | public override DataTemplate SelectTemplate(object item, DependencyObject container)
16 | {
17 | if (item is null)
18 | return null;
19 |
20 | return item switch
21 | {
22 | WaitingOpProgressViewModel => WaitingOpProgressTemplate,
23 | InProgSyncProgressViewModel => InProgSyncProgressTemplate,
24 | InProgShellProgressViewModel => InProgShellProgressTemplate,
25 | CompletedSyncProgressViewModel => CompletedSyncProgressTemplate,
26 | CompletedShellProgressViewModel => CompletedShellProgressTemplate,
27 | CanceledOpProgressViewModel => CanceledOpProgressTemplate,
28 | FailedOpProgressViewModel => FailedOpProgressTemplate,
29 | _ => throw new NotSupportedException(),
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/TemplateSelectors/FileOpTreeTemplateSelector.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 |
3 | namespace ADB_Explorer.Helpers;
4 |
5 | internal class FileOpTreeTemplateSelector : DataTemplateSelector
6 | {
7 | public HierarchicalDataTemplate FileOpTreeFolderTemplate { get; set; }
8 |
9 | public HierarchicalDataTemplate FileOpTreeFileTemplate { get; set; }
10 |
11 | public override DataTemplate SelectTemplate(object item, DependencyObject container)
12 | {
13 | return item switch
14 | {
15 | SyncFile dir when dir.IsDirectory => FileOpTreeFolderTemplate,
16 | SyncFile => FileOpTreeFileTemplate,
17 | _ => throw new NotSupportedException(),
18 | };
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/TemplateSelectors/FileOperationTemplateSelector.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Services;
2 |
3 | namespace ADB_Explorer.Helpers;
4 |
5 | public class FileOperationTemplateSelector : DataTemplateSelector
6 | {
7 | public DataTemplate PullTemplate { get; set; }
8 | public DataTemplate PushTemplate { get; set; }
9 | public DataTemplate SyncTemplate { get; set; }
10 |
11 | public override DataTemplate SelectTemplate(object item, DependencyObject container)
12 | {
13 | return item switch
14 | {
15 | FileSyncOperation op when op.OperationName is FileOperation.OperationType.Pull => PullTemplate,
16 | FileSyncOperation op when op.OperationName is FileOperation.OperationType.Push => PushTemplate,
17 | FileSyncOperation => SyncTemplate,
18 | _ => throw new NotImplementedException(),
19 | };
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/TemplateSelectors/SettingsGroupTemplateSelector.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Services;
2 |
3 | namespace ADB_Explorer.Helpers;
4 |
5 | public class SettingsGroupTemplateSelector : DataTemplateSelector
6 | {
7 | public DataTemplate SettingsGroupTemplate { get; set; }
8 | public DataTemplate SettingsSeparatorTemplate { get; set; }
9 |
10 | public override DataTemplate SelectTemplate(object item, DependencyObject container)
11 | {
12 | return item switch
13 | {
14 | SettingsGroup => SettingsGroupTemplate,
15 | SettingsSeparator => SettingsSeparatorTemplate,
16 | Ungrouped => null,
17 | _ => throw new NotImplementedException(),
18 | };
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ADB Explorer/Helpers/TemplateSelectors/SettingsTemplateSelector.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Services;
2 |
3 | namespace ADB_Explorer.Helpers;
4 |
5 | public class SettingsTemplateSelector : DataTemplateSelector
6 | {
7 | public DataTemplate BoolSettingTemplate { get; set; }
8 | public DataTemplate StringSettingTemplate { get; set; }
9 | public DataTemplate EnumSettingTemplate { get; set; }
10 | public DataTemplate ComboSettingTemplate { get; set; }
11 |
12 | public override DataTemplate SelectTemplate(object item, DependencyObject container)
13 | {
14 | return item switch
15 | {
16 | BoolSetting => BoolSettingTemplate,
17 | StringSetting => StringSettingTemplate,
18 | EnumSetting => EnumSettingTemplate,
19 | ComboSetting => ComboSettingTemplate,
20 | _ => throw new NotImplementedException(),
21 | };
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/Device/Device.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.ViewModels;
2 |
3 | namespace ADB_Explorer.Models;
4 |
5 | public abstract class AbstractDevice : ViewModelBase
6 | {
7 | public enum DeviceType
8 | {
9 | Service,
10 | Local,
11 | Remote,
12 | Recovery,
13 | Sideload,
14 | WSA,
15 | Emulator,
16 | History,
17 | New,
18 | }
19 |
20 | public enum DeviceStatus
21 | {
22 | Ok, // online \ does not require attention
23 | Offline,
24 | Unauthorized,
25 | }
26 |
27 | public enum RootStatus
28 | {
29 | Unchecked,
30 | Forbidden,
31 | Disabled,
32 | Enabled,
33 | }
34 | }
35 |
36 | public abstract class Device : AbstractDevice
37 | {
38 | #region Full properties
39 |
40 | private DeviceType type;
41 | public virtual DeviceType Type
42 | {
43 | get => type;
44 | protected set => Set(ref type, value);
45 | }
46 |
47 | private DeviceStatus status;
48 | public virtual DeviceStatus Status
49 | {
50 | get => status;
51 | set => Set(ref status, value);
52 | }
53 |
54 | private string ipAddress;
55 | public virtual string IpAddress
56 | {
57 | get => ipAddress;
58 | set => Set(ref ipAddress, value);
59 | }
60 |
61 | public virtual string ID { get; protected set; }
62 |
63 | #endregion
64 |
65 | public static implicit operator bool(Device obj)
66 | {
67 | return obj is not null && !string.IsNullOrEmpty(obj.ID);
68 | }
69 | }
70 |
71 | ///
72 | /// Represents all device types that require pairing properties
73 | ///
74 | public abstract class PairingDevice : Device
75 | {
76 | #region Full properties
77 |
78 | private string pairingPort;
79 | public virtual string PairingPort
80 | {
81 | get => pairingPort;
82 | set => Set(ref pairingPort, value);
83 | }
84 |
85 | private string pairingCode;
86 | public string PairingCode
87 | {
88 | get => pairingCode;
89 | set => Set(ref pairingCode, value);
90 | }
91 |
92 | #endregion
93 | }
94 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/Device/HistoryDevice.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Models;
2 |
3 | public class HistoryDevice : NewDevice
4 | {
5 | private string deviceName = null;
6 | public string DeviceName
7 | {
8 | get => deviceName;
9 | set => Set(ref deviceName, value);
10 | }
11 |
12 | public HistoryDevice()
13 | {
14 | Type = DeviceType.History;
15 | Status = DeviceStatus.Ok;
16 | }
17 |
18 | public HistoryDevice(NewDevice device) : this()
19 | {
20 | IpAddress = device.IpAddress;
21 | ConnectPort = device.ConnectPort;
22 | }
23 |
24 | [JsonConstructor]
25 | public HistoryDevice(string ipAddress, string connectPort, string deviceName = "") : this()
26 | {
27 | DeviceName = deviceName;
28 | IpAddress = ipAddress;
29 | ConnectPort = connectPort;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/Device/NewDevice.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Models;
2 |
3 | public class NewDevice : PairingDevice
4 | {
5 | private string connectPort;
6 | public string ConnectPort
7 | {
8 | get => connectPort;
9 | set => Set(ref connectPort, value);
10 | }
11 |
12 | private string hostName;
13 | public string HostName
14 | {
15 | get => hostName;
16 | set => Set(ref hostName, value);
17 | }
18 |
19 | public NewDevice()
20 | {
21 | Type = DeviceType.New;
22 | Status = DeviceStatus.Ok;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/Device/ServiceDevice.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Models;
2 |
3 | ///
4 | /// Represents all services acquired by mdns services
5 | ///
6 | public abstract class ServiceDevice : PairingDevice
7 | {
8 | public enum ServiceType
9 | {
10 | QrCode,
11 | PairingCode
12 | }
13 |
14 | #region Full properties
15 |
16 | private ServiceType mdnsType;
17 | public ServiceType MdnsType
18 | {
19 | get => mdnsType;
20 | set => Set(ref mdnsType, value);
21 | }
22 |
23 | #endregion
24 |
25 | public ServiceDevice()
26 | {
27 | Type = DeviceType.Service;
28 | }
29 |
30 | public ServiceDevice(string id, string ipAddress, string port = "") : this()
31 | {
32 | PropertyChanged += ServiceDevice_PropertyChanged;
33 |
34 | ID = id;
35 | IpAddress = ipAddress;
36 | PairingPort = port;
37 | }
38 |
39 | private void ServiceDevice_PropertyChanged(object sender, PropertyChangedEventArgs e)
40 | {
41 | if (e.PropertyName is nameof(PairingPort) or nameof(MdnsType))
42 | {
43 | UpdateStatus();
44 | }
45 | }
46 |
47 | private void UpdateStatus()
48 | {
49 | Status = MdnsType is ServiceType.QrCode ? DeviceStatus.Ok : DeviceStatus.Unauthorized;
50 | }
51 | }
52 |
53 | public class PairingService : ServiceDevice
54 | {
55 | public PairingService(string id, string ipAddress, string port) : base(id, ipAddress, port)
56 | { }
57 | }
58 |
59 | public class ConnectService : ServiceDevice
60 | {
61 | public ConnectService(string id, string ipAddress, string port) : base(id, ipAddress, port)
62 | { }
63 | }
64 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/Device/WsaPkgDevice.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Models;
2 |
3 | public class WsaPkgDevice : Device
4 | {
5 | private DateTime lastLaunch = DateTime.MinValue;
6 | public DateTime LastLaunch
7 | {
8 | get => lastLaunch;
9 | set => Set(ref lastLaunch, value);
10 | }
11 |
12 | public WsaPkgDevice()
13 | {
14 | Type = DeviceType.WSA;
15 | Status = DeviceStatus.Offline;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/Drive/Drive.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.ViewModels;
2 | using static ADB_Explorer.Models.AdbExplorerConst;
3 |
4 | namespace ADB_Explorer.Models;
5 |
6 | public abstract class AbstractDrive : ViewModelBase
7 | {
8 | public enum DriveType
9 | {
10 | Root,
11 | Internal,
12 | Expansion,
13 | External,
14 | Emulated,
15 | Unknown,
16 | Trash,
17 | Temp,
18 | Package,
19 | }
20 |
21 | private DriveType type = DriveType.Unknown;
22 | public DriveType Type
23 | {
24 | get => type;
25 | set => Set(ref type, value);
26 | }
27 |
28 |
29 | public static implicit operator bool(AbstractDrive obj)
30 | {
31 | return obj is not null;
32 | }
33 |
34 | public string DisplayName
35 | {
36 | get => GetDriveDisplayName(Type);
37 | }
38 |
39 | public static string GetDriveDisplayName(DriveType type) => type switch
40 | {
41 | DriveType.Root => Strings.Resources.S_DRIVE_ROOT,
42 | DriveType.Internal => Strings.Resources.S_DRIVE_INTERNAL_STORAGE,
43 | DriveType.Expansion => Strings.Resources.S_DRIVE_SD,
44 | DriveType.External => Strings.Resources.S_DRIVE_OTG,
45 | DriveType.Unknown => "",
46 | DriveType.Emulated => Strings.Resources.S_DRIVE_EMULATED,
47 | DriveType.Trash => Strings.Resources.S_DRIVE_TRASH,
48 | DriveType.Temp => Strings.Resources.S_DRIVE_TEMP,
49 | DriveType.Package => Strings.Resources.S_DRIVE_APPS,
50 | _ => null,
51 | };
52 | }
53 |
54 | public class Drive : AbstractDrive
55 | {
56 | public string Path { get; protected set; }
57 |
58 | ///
59 | /// Filesystem in USEr space. An emulated / virtual filesystem on Android.
60 | /// Does not support:
61 | /// • Symbolic links
62 | /// • Special chars in file name (like NTFS)
63 | /// • Installing APK from it
64 | ///
65 | public virtual bool IsFUSE { get; }
66 |
67 |
68 | public Drive(string path = "")
69 | {
70 | Path = path;
71 |
72 | if (Type is DriveType.Unknown && DRIVE_TYPES.TryGetValue(path, out var type))
73 | {
74 | Type = type;
75 | if (Type is DriveType.Internal)
76 | Path = "/sdcard";
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/Drive/LogicalDrive.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Converters;
2 |
3 | namespace ADB_Explorer.Models;
4 |
5 | public class LogicalDrive : Drive
6 | {
7 | private string size;
8 | public string Size
9 | {
10 | get => size;
11 | set => Set(ref size, value);
12 | }
13 |
14 | private string used;
15 | public string Used
16 | {
17 | get => used;
18 | set => Set(ref used, value);
19 | }
20 |
21 | private string available;
22 | public string Available
23 | {
24 | get => available;
25 | set => Set(ref available, value);
26 | }
27 |
28 | private sbyte usageP;
29 | public sbyte UsageP
30 | {
31 | get => usageP;
32 | set => Set(ref usageP, value);
33 | }
34 |
35 | private string fileSystem = "";
36 | public string FileSystem
37 | {
38 | get => fileSystem;
39 | set
40 | {
41 | if (Set(ref fileSystem, value))
42 | OnPropertyChanged(nameof(IsFUSE));
43 | }
44 | }
45 |
46 | public override bool IsFUSE => FileSystem.Contains("fuse");
47 |
48 | public string ID => Path.Count(c => c == '/') > 1 ? Path[(Path.LastIndexOf('/') + 1)..] : Path;
49 |
50 |
51 | public LogicalDrive(string size = "",
52 | string used = "",
53 | string available = "",
54 | sbyte usageP = -1,
55 | string path = "",
56 | bool isMMC = false,
57 | bool isEmulator = false,
58 | string fileSystem = "")
59 | : base(path)
60 | {
61 | if (usageP is < -1 or > 100)
62 | throw new ArgumentOutOfRangeException(nameof(usageP));
63 |
64 | Size = size;
65 | Used = used;
66 | Available = available;
67 | UsageP = usageP;
68 |
69 | if (isMMC)
70 | {
71 | Type = DriveType.Expansion;
72 | }
73 | else if (isEmulator)
74 | {
75 | Type = DriveType.Emulated;
76 | }
77 |
78 | FileSystem = fileSystem;
79 | }
80 |
81 | public LogicalDrive(GroupCollection match, bool isMMC = false, bool isEmulator = false, string forcePath = "")
82 | : this(
83 | (ulong.Parse(match["size_kB"].Value) * 1024).ToSize(true, 2, 2),
84 | (ulong.Parse(match["used_kB"].Value) * 1024).ToSize(true, 2, 2),
85 | (ulong.Parse(match["available_kB"].Value) * 1024).ToSize(true, 2, 2),
86 | sbyte.Parse(match["usage_P"].Value),
87 | string.IsNullOrEmpty(forcePath) ? match["path"].Value : forcePath,
88 | isMMC,
89 | isEmulator,
90 | match["FileSystem"].Value)
91 | { }
92 | }
93 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/Drive/VirtualDrive.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Models;
2 |
3 | public class VirtualDrive : Drive
4 | {
5 | private long? itemsCount = 0;
6 | public long? ItemsCount
7 | {
8 | get => itemsCount;
9 | set => Set(ref itemsCount, value);
10 | }
11 |
12 | public override bool IsFUSE => Type switch
13 | {
14 | // Temp drive is under the root filesystem
15 | DriveType.Temp => Data.DevicesObject.Current?.Drives?.Find(d => d.Type is DriveType.Root).IsFUSE is true,
16 | // App drive isn't really a drive, and the recycle bin doesn't allow any of the actions limited on FUSE
17 | // So it is useless to display the icon
18 | _ => false,
19 | };
20 |
21 | public VirtualDrive(string path = "", long itemsCount = 0) : base(path)
22 | {
23 | ItemsCount = itemsCount;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/File/FileStat.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Models;
2 |
3 | public class FileStat : AbstractFile, IBaseFile, IFileStat
4 | {
5 | public FileStat(string fileName,
6 | string path,
7 | FileType type,
8 | bool isLink,
9 | ulong? size,
10 | DateTime? modifiedTime)
11 | {
12 | FullName = fileName;
13 | FullPath = path;
14 |
15 | Type = type;
16 | Size = size;
17 | ModifiedTime = modifiedTime;
18 |
19 | IsLink = isLink;
20 | }
21 |
22 | public string FullName { get; set; }
23 |
24 | public string FullPath { get; set; }
25 |
26 | public FileType Type { get; set; }
27 |
28 | public ulong? Size { get; set; }
29 |
30 | public DateTime? ModifiedTime { get; set; }
31 |
32 | public bool IsLink { get; set; }
33 | }
34 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/File/IBaseFile.cs:
--------------------------------------------------------------------------------
1 | using static ADB_Explorer.Models.AbstractFile;
2 |
3 | namespace ADB_Explorer.Models;
4 |
5 | ///
6 | /// Represents the basic properties returned by the `stat` command on Android devices.
7 | ///
8 | public interface IFileStat
9 | {
10 | public FileType Type { get; set; }
11 |
12 | public ulong? Size { get; set; }
13 |
14 | public DateTime? ModifiedTime { get; set; }
15 |
16 | public bool IsLink { get; set; }
17 | }
18 |
19 | ///
20 | /// Represents the basic properties of a file or directory.
21 | ///
22 | public interface IBaseFile
23 | {
24 | public string FullName { get; }
25 |
26 | public string FullPath { get; }
27 | }
28 |
29 | ///
30 | /// Represents the items that can be displayed in the browser - and .
31 | ///
32 | public interface IBrowserItem
33 | {
34 | public string DisplayName { get; }
35 | }
36 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/File/Package.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.ViewModels;
2 |
3 | namespace ADB_Explorer.Models;
4 |
5 | public class Package : ViewModelBase, IBrowserItem
6 | {
7 | public enum PackageType
8 | {
9 | System,
10 | User,
11 | }
12 |
13 | private string name;
14 | public string Name
15 | {
16 | get => name;
17 | set => Set(ref name, value);
18 | }
19 |
20 | public string DisplayName => Name;
21 |
22 | private PackageType type;
23 | public PackageType Type
24 | {
25 | get => type;
26 | set => Set(ref type, value);
27 | }
28 |
29 | private long? uid = null;
30 | public long? Uid
31 | {
32 | get => uid;
33 | set => Set(ref uid, value);
34 | }
35 |
36 | private long? version = null;
37 | public long? Version
38 | {
39 | get => version;
40 | set => Set(ref version, value);
41 | }
42 |
43 | public static Package New(string package, PackageType type)
44 | {
45 | var match = AdbRegEx.RE_PACKAGE_LISTING().Match(package);
46 | if (!match.Success)
47 | return null;
48 |
49 | return new Package(match.Groups["package"].Value, type, match.Groups["uid"].Value, match.Groups["version"].Value);
50 | }
51 |
52 | public Package(string name, PackageType type, string uid, string version)
53 | {
54 | Name = name;
55 | Type = type;
56 |
57 | if (long.TryParse(uid, out long resU))
58 | Uid = resU;
59 |
60 | if (long.TryParse(version, out long resV))
61 | Version = resV;
62 | }
63 |
64 | public override string ToString()
65 | {
66 | return $"{Name}\n{Type}\n{Uid}\n{Version}";
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/File/SyncFile.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Helpers;
2 | using ADB_Explorer.Services;
3 | using Vanara.Windows.Shell;
4 |
5 | namespace ADB_Explorer.Models;
6 |
7 | public class SyncFile : FilePath
8 | {
9 | public ObservableList ProgressUpdates { get; } = [];
10 |
11 | public ObservableList Children { get; } = [];
12 |
13 | public ulong? Size { get; }
14 |
15 | public SyncFile(string androidPath, FileType fileType = FileType.File)
16 | : base(androidPath, fileType: fileType)
17 | {
18 |
19 | }
20 |
21 | public SyncFile(ShellItem windowsPath)
22 | : base(windowsPath)
23 | {
24 | Size = IsDirectory ? null : (ulong?)windowsPath.FileInfo.Length;
25 | }
26 |
27 | public SyncFile(FileClass fileClass)
28 | : base(fileClass.FullPath, fileClass.FullName, fileClass.Type)
29 | {
30 | Size = fileClass.Size;
31 | }
32 |
33 | public void AddUpdates(params FileOpProgressInfo[] newUpdates)
34 | => AddUpdates(newUpdates.Where(o => o is not null));
35 |
36 | public void AddUpdates(IEnumerable newUpdates, FileOperation fileOp = null)
37 | {
38 | if (!newUpdates.Any())
39 | return;
40 |
41 | if (!IsDirectory || newUpdates.All(u => u.AndroidPath is not null && u.AndroidPath.Equals(FullPath)))
42 | {
43 | ProgressUpdates.AddRange(newUpdates);
44 | return;
45 | }
46 |
47 | if (fileOp is FileSyncOperation)
48 | {
49 | foreach (var update in newUpdates)
50 | {
51 | if (string.IsNullOrEmpty(update.AndroidPath))
52 | update.SetPathToCurrent(fileOp);
53 | }
54 | }
55 | else
56 | newUpdates = newUpdates.Where(u => !string.IsNullOrEmpty(u.AndroidPath));
57 |
58 | var groups = newUpdates.GroupBy(update => DirectChildPath(update.AndroidPath));
59 |
60 | foreach (var group in groups.Where(g => g.Key is not null))
61 | {
62 | SyncFile file = Children.FirstOrDefault(child => child.FullPath.Equals(group.Key));
63 |
64 | if (file is null)
65 | {
66 | bool isDir = !group.Key.Equals(group.First().AndroidPath);
67 | file = new(group.Key, isDir ? FileType.Folder : FileType.File);
68 |
69 | ExecuteInDispatcher(() =>
70 | {
71 | Children.Add(file);
72 |
73 | OnPropertyChanged(nameof(Children));
74 | });
75 | }
76 |
77 | file.AddUpdates(group);
78 | }
79 | }
80 |
81 | public string DirectChildPath(string fullPath)
82 | => FileHelper.DirectChildPath(FullPath, fullPath);
83 | }
84 |
85 | public class SyncFileComparer : IEqualityComparer
86 | {
87 | public bool Equals(SyncFile x, SyncFile y)
88 | => x.FullPath.Equals(y.FullPath);
89 |
90 | public int GetHashCode([DisallowNull] SyncFile obj)
91 | {
92 | throw new NotImplementedException();
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/File/TrashIndexer.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Services;
2 | using ADB_Explorer.ViewModels;
3 |
4 | namespace ADB_Explorer.Models;
5 |
6 | public class TrashIndexer : ViewModelBase
7 | {
8 | private string recycleName;
9 | public string RecycleName
10 | {
11 | get => recycleName;
12 | set => Set(ref recycleName, value);
13 | }
14 |
15 | private string originalPath;
16 | public string OriginalPath
17 | {
18 | get => originalPath;
19 | set => Set(ref originalPath, value);
20 | }
21 |
22 | private DateTime? dateModified;
23 | public DateTime? DateModified
24 | {
25 | get => dateModified;
26 | set => Set(ref dateModified, value);
27 | }
28 |
29 | public string ModifiedTimeString => DateModified?.ToString(CultureInfo.CurrentCulture.DateTimeFormat);
30 |
31 | public string IndexerPath => $"{AdbExplorerConst.RECYCLE_PATH}/.{RecycleName}{AdbExplorerConst.RECYCLE_INDEX_SUFFIX}";
32 |
33 | public string ParentPath
34 | {
35 | get
36 | {
37 | int originalIndex = OriginalPath.LastIndexOf('/');
38 | Index index;
39 | if (originalIndex == 0)
40 | index = 1;
41 | else if (originalIndex < 0)
42 | index = ^0;
43 | else
44 | index = originalIndex;
45 |
46 | return OriginalPath[..index];
47 | }
48 | }
49 |
50 | public TrashIndexer()
51 | { }
52 |
53 | public TrashIndexer(string recycleIndex) : this(recycleIndex.Split('|'))
54 | { }
55 |
56 | public TrashIndexer(params string[] recycleIndex) : this(recycleIndex[0], recycleIndex[1], recycleIndex[2])
57 | { }
58 |
59 | public TrashIndexer(string recycleName, string originalPath, string dateModified)
60 | : this(recycleName, originalPath, DateTime.TryParseExact(dateModified, AdbExplorerConst.ADB_EXPLORER_DATE_FORMAT, null, DateTimeStyles.None, out var res) ? res : null)
61 | { }
62 |
63 | public TrashIndexer(string recycleName, string originalPath, DateTime? dateModified)
64 | {
65 | RecycleName = recycleName;
66 | OriginalPath = originalPath;
67 | DateModified = dateModified;
68 | }
69 |
70 | public TrashIndexer(FileMoveOperation op)
71 | {
72 | RecycleName = op.RecycleName;
73 | OriginalPath = op.FilePath.FullPath;
74 | DateModified = op.DateModified;
75 | }
76 |
77 | public override string ToString()
78 | {
79 | var date = DateModified is null ? "?" : DateModified.Value.ToString(AdbExplorerConst.ADB_EXPLORER_DATE_FORMAT);
80 | return $"{RecycleName}|{OriginalPath}|{date}";
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/FileOpFilter.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Helpers;
2 | using ADB_Explorer.Services;
3 | using ADB_Explorer.ViewModels;
4 |
5 | namespace ADB_Explorer.Models;
6 |
7 | public static class FileOpFilters
8 | {
9 | private static List list = null;
10 | public static List List
11 | {
12 | get
13 | {
14 | if (list is null)
15 | {
16 | list = [.. Enum.GetValues().Select(f => new FileOpFilter(f))];
17 |
18 | UpdateCheckedColumns();
19 | }
20 |
21 | return list;
22 | }
23 | }
24 |
25 | public static ObservableProperty CheckedFilterCount { get; private set; } = new() { Value = -1 };
26 |
27 | public static void UpdateCheckedColumns() =>
28 | CheckedFilterCount.Value = List.Count(col => col.IsChecked is true);
29 | }
30 |
31 | public class FileOpFilter : ViewModelBase
32 | {
33 | public enum FilterType
34 | {
35 | Running,
36 | Pending,
37 | Completed,
38 | Validated,
39 | Failed,
40 | Canceled,
41 | Previous,
42 | }
43 |
44 | private bool? isChecked = null;
45 | public bool? IsChecked
46 | {
47 | get => isChecked;
48 | set
49 | {
50 | if (Set(ref isChecked, value))
51 | {
52 | if (FileOpFilters.CheckedFilterCount > 0)
53 | FileOpFilters.UpdateCheckedColumns();
54 |
55 | Store();
56 | }
57 | }
58 | }
59 |
60 | private CheckBox checkBox = null;
61 | public CheckBox CheckBox
62 | {
63 | get
64 | {
65 | if (checkBox is null)
66 | {
67 | checkBox = new CheckBox()
68 | {
69 | Style = (Style)App.Current.FindResource("FileOpFilterCheckBox"),
70 | DataContext = this,
71 | Content = AdbExplorerConst.FILE_OP_NAMES[Type],
72 | Margin = new(0, -6, 0, -6),
73 | };
74 | }
75 |
76 | return checkBox;
77 | }
78 | }
79 |
80 | public FilterType Type { get; }
81 |
82 | public bool IsEnabled
83 | {
84 | get
85 | {
86 | if (IsChecked is null)
87 | return false;
88 |
89 | return IsChecked is false || FileOpFilters.CheckedFilterCount > 1;
90 | }
91 | }
92 |
93 | public FileOpFilter(FilterType type)
94 | {
95 | Type = type;
96 |
97 | if (type is FilterType.Running)
98 | IsChecked = null;
99 | else
100 | IsChecked = Retrieve() is bool val ? val : true;
101 |
102 | FileOpFilters.CheckedFilterCount.PropertyChanged += (object sender, PropertyChangedEventArgs e) => OnPropertyChanged(nameof(IsEnabled));
103 | }
104 |
105 | private bool? Retrieve() => Storage.RetrieveBool($"{nameof(FilterType)}_{Type}");
106 |
107 | private void Store() => Storage.StoreValue($"{nameof(FilterType)}_{Type}", $"{IsChecked}");
108 | }
109 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/Log.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Models;
2 |
3 | internal class Log
4 | {
5 | public string Content { get; set; }
6 |
7 | public DateTime TimeStamp { get; set; }
8 |
9 | public Log(string content, DateTime? timeStamp = null)
10 | {
11 | Content = content;
12 | TimeStamp = timeStamp is null ? DateTime.Now : timeStamp.Value;
13 | }
14 |
15 | public override string ToString()
16 | {
17 | return $"{TimeStamp:HH:mm:ss:fff} ⁞ {Content}";
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/ADB Explorer/Models/Static/Data.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Helpers;
2 | using ADB_Explorer.Services;
3 | using ADB_Explorer.ViewModels;
4 |
5 | namespace ADB_Explorer.Models;
6 |
7 | internal static class Data
8 | {
9 | public static ADBService.AdbDevice CurrentADBDevice { get; set; } = null;
10 |
11 | public static string CurrentPath { get; set; }
12 | public static string ParentPath { get; set; }
13 |
14 | public static DriveViewModel CurrentDrive { get; set; } = null;
15 |
16 | public static FileOperationQueue FileOpQ { get; set; }
17 |
18 | public static Dictionary CurrentDisplayNames { get; set; } = [];
19 |
20 | public static AppSettings Settings { get; set; } = new();
21 |
22 | public static AppRuntimeSettings RuntimeSettings { get; set; } = new();
23 |
24 | public static CopyPasteService CopyPaste { get; } = new();
25 |
26 | public static ObservableCollection CommandLog { get; set; } = [];
27 |
28 | public static ObservableList RecycleIndex { get; set; } = [];
29 |
30 | public static ObservableList Packages { get; set; } = [];
31 |
32 | public static Version AppVersion => new(Properties.AppGlobal.AppVersion);
33 |
34 | public static FileActionsEnable FileActions { get; set; } = new();
35 |
36 | public static DirectoryLister DirList { get; set; }
37 |
38 | public static string AppDataPath { get; set; } = "";
39 |
40 | public static string ProgressRedirectionPath { get; set; } = null;
41 |
42 | public static Devices DevicesObject { get; set; }
43 |
44 | public static MDNS MdnsService { get; set; } = new();
45 |
46 | public static PairingQrClass QrClass { get; set; }
47 |
48 | public static IEnumerable SelectedFiles { get; set; } = Enumerable.Empty();
49 |
50 | public static IEnumerable SelectedPackages { get; set; } = Enumerable.Empty();
51 | }
52 |
--------------------------------------------------------------------------------
/ADB Explorer/PortableLauncher.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | start "" "ADB Explorer.exe" ./
3 | exit
--------------------------------------------------------------------------------
/ADB Explorer/Resources/APK_format_icon_2014-2019_.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Explorer/Resources/APK_format_icon_2014-2019_.ico
--------------------------------------------------------------------------------
/ADB Explorer/Resources/AdbProgressRedirection_ARM:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Explorer/Resources/AdbProgressRedirection_ARM
--------------------------------------------------------------------------------
/ADB Explorer/Resources/AdbProgressRedirection_x86:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Explorer/Resources/AdbProgressRedirection_x86
--------------------------------------------------------------------------------
/ADB Explorer/Resources/Fonts/Nunito-VariableFont_wght.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Explorer/Resources/Fonts/Nunito-VariableFont_wght.ttf
--------------------------------------------------------------------------------
/ADB Explorer/Resources/Links.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 |
3 | namespace ADB_Explorer.Resources;
4 |
5 | public static class Links
6 | {
7 | public static readonly Uri L_ADB_PAGE = Data.RuntimeSettings.IsAppDeployed
8 | ? new("https://developer.android.com/studio/command-line/adb")
9 | : new("https://developer.android.com/tools/releases/platform-tools");
10 | public static readonly Uri L_CC_LIC = new("https://creativecommons.org/licenses/by-sa/3.0/");
11 | public static readonly Uri L_APACHE_LIC = new("https://www.apache.org/licenses/LICENSE-2.0");
12 | public static readonly Uri REPO_RELEASES_URL = new("https://api.github.com/repos/Alex4SSB/ADB-Explorer/releases");
13 | public static readonly Uri MODERN_WPF = new("https://github.com/Kinnara/ModernWpf");
14 | public static readonly Uri ICONS8 = new("https://icons8.com");
15 | public static readonly Uri ADB_EXPLORER_PRIVACY = new("https://github.com/Alex4SSB/ADB-Explorer/blob/master/Privacy.md");
16 | public static readonly Uri ADB_EXPLORER_GITHUB = new("https://github.com/Alex4SSB/ADB-Explorer");
17 | public static readonly Uri LGPL3 = new("https://opensource.org/license/lgpl-3-0");
18 | public static readonly Uri SPONSOR = new("https://github.com/sponsors/Alex4SSB");
19 | }
20 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/ADB/MDNS.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 | using ADB_Explorer.ViewModels;
3 |
4 | namespace ADB_Explorer.Services;
5 |
6 | public class MDNS : ViewModelBase
7 | {
8 | public MDNS()
9 | {
10 | State = MdnsState.Disabled;
11 | }
12 |
13 | public enum MdnsState
14 | {
15 | Disabled,
16 | InProgress,
17 | NotRunning,
18 | Running,
19 | }
20 |
21 | private MdnsState state;
22 | public MdnsState State
23 | {
24 | get => state;
25 | set
26 | {
27 | if (Set(ref state, value))
28 | {
29 | if (value is MdnsState.InProgress)
30 | checkStart = DateTime.Now;
31 | else
32 | Progress = 0.0;
33 | }
34 | }
35 | }
36 |
37 | public void CheckMdns()
38 | {
39 | if (ADBService.CheckMDNS())
40 | State = MdnsState.Running;
41 | else
42 | State = MdnsState.NotRunning;
43 | }
44 |
45 | private double progress;
46 | public double Progress
47 | {
48 | get => progress;
49 | set
50 | {
51 | if (Set(ref progress, value))
52 | OnPropertyChanged(nameof(TimePassedString));
53 | }
54 | }
55 |
56 | private DateTime checkStart;
57 |
58 | private TimeSpan timePassed = TimeSpan.MinValue;
59 |
60 | public string TimePassedString => timePassed == TimeSpan.MinValue ? "" : Converters.UnitConverter.ToTime((decimal)timePassed.TotalSeconds, useMilli: false, digits: 0);
61 |
62 | public void UpdateProgress()
63 | {
64 | timePassed = DateTime.Now.Subtract(checkStart);
65 |
66 | Progress = timePassed < AdbExplorerConst.MDNS_DOWN_RESPONSE_TIME
67 | ? timePassed / AdbExplorerConst.MDNS_DOWN_RESPONSE_TIME * 100
68 | : 100;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/ADB/WiFiPairingService.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Helpers;
2 | using ADB_Explorer.Models;
3 | using static ADB_Explorer.Models.AdbExplorerConst;
4 |
5 | namespace ADB_Explorer.Services;
6 |
7 | public class PairingQrClass
8 | {
9 | public string ServiceName { get; }
10 | public string Password { get; }
11 | public SolidColorBrush Background { get; }
12 | public SolidColorBrush Foreground { get; }
13 |
14 | public DrawingImage Image => string.IsNullOrEmpty(PairingString) ? null : QrGenerator.GenerateQR(PairingString, Background, Foreground);
15 | public string PairingString => WiFiPairingService.CreatePairingString(ServiceName, Password);
16 |
17 | public PairingQrClass()
18 | {
19 | ServiceName = PAIRING_SERVICE_PREFIX + RandomString.GetUniqueKey(10);
20 | Password = RandomString.GetUniqueKey(12);
21 |
22 | Background = (SolidColorBrush)App.Current.FindResource("QrBackgroundBrush");
23 | Foreground = (SolidColorBrush)App.Current.FindResource("QrForegroundBrush");
24 | }
25 | }
26 |
27 | public class WiFiPairingService
28 | {
29 | /**
30 | * Format is "WIFI:T:ADB;S:service;P:password;;" (without the quotes)
31 | */
32 | public static string CreatePairingString(string service, string password)
33 | {
34 | return $"WIFI:T:ADB;S:{service};P:{password};;";
35 | }
36 |
37 | public static IEnumerable GetServices()
38 | {
39 | ADBService.ExecuteAdbCommand("mdns", out string services, out _, new(), "services");
40 |
41 | List mdnsServices = [];
42 | var matches = AdbRegEx.RE_MDNS_SERVICE().Matches(services);
43 | foreach (Match item in matches)
44 | {
45 | var id = item.Groups["ID"].Value;
46 | var portType = item.Groups["PortType"].Value;
47 | var ipAddress = item.Groups["IpAddress"].Value;
48 | var port = item.Groups["Port"].Value;
49 |
50 | if (LOOPBACK_ADDRESSES.Contains(ipAddress))
51 | continue;
52 |
53 | ServiceDevice service = portType == "pairing"
54 | ? new PairingService(id, ipAddress, port)
55 | : new ConnectService(id, ipAddress, port);
56 |
57 | service.MdnsType = id.Contains(PAIRING_SERVICE_PREFIX)
58 | ? ServiceDevice.ServiceType.QrCode
59 | : ServiceDevice.ServiceType.PairingCode;
60 |
61 | mdnsServices.Add(service);
62 | }
63 |
64 | return mdnsServices.Distinct();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/AppInfra/DebugLog.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Services;
2 |
3 | public static class DebugLog
4 | {
5 | private static readonly Mutex mutex = new();
6 |
7 | public static void PrintLine(string message)
8 | {
9 | mutex.WaitOne();
10 |
11 | if (!string.IsNullOrEmpty(Properties.AppGlobal.DragDropLogPath))
12 | File.AppendAllText(Properties.AppGlobal.DragDropLogPath, $"{DateTime.Now:HH:mm:ss:fff} | {message}\n");
13 |
14 | mutex.ReleaseMutex();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/AppInfra/FileAction/ToggleMenu.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Helpers;
2 | using ADB_Explorer.ViewModels;
3 |
4 | namespace ADB_Explorer.Services;
5 |
6 | internal class ToggleMenu : ViewModelBase
7 | {
8 | public ObservableProperty IsChecked { get; set; } = new();
9 |
10 | public ObservableProperty Description { get; private set; } = new();
11 |
12 | public ObservableProperty Icon { get; private set; } = new();
13 |
14 | public FileAction FileAction { get; }
15 |
16 | public DualActionButton Button { get; }
17 |
18 | public ToggleMenu(FileAction.FileActionType type,
19 | Func canExecute,
20 | string checkedDescription,
21 | string checkedIcon,
22 | Action action,
23 | string uncheckedDescription = "",
24 | string uncheckedIcon = "",
25 | KeyGesture gesture = null,
26 | Brush checkBackground = null,
27 | IEnumerable children = null,
28 | ObservableProperty isVisible = null,
29 | bool toggleOnClick = true,
30 | bool clearClipboard = false)
31 | {
32 | uncheckedDescription = string.IsNullOrEmpty(uncheckedDescription) ? checkedDescription : uncheckedDescription;
33 | uncheckedIcon = string.IsNullOrEmpty(uncheckedIcon) ? checkedIcon : uncheckedIcon;
34 |
35 | IsChecked.Value = false;
36 | Description.Value = uncheckedDescription;
37 | Icon.Value = uncheckedIcon;
38 |
39 | FileAction = new(type, canExecute, action, Description, gesture, gesture is not null, clearClipboard);
40 | Button = new(FileAction, Icon, IsChecked, checkBackground: checkBackground, children: children, isVisible: isVisible, isCheckable: toggleOnClick);
41 |
42 | IsChecked.PropertyChanged += (object sender, PropertyChangedEventArgs e) =>
43 | {
44 | Description.Value = e.NewValue ? checkedDescription : uncheckedDescription;
45 | Icon.Value = e.NewValue ? checkedIcon : uncheckedIcon;
46 | };
47 | }
48 |
49 | public void Toggle(bool? toggle = null)
50 | {
51 | if (toggle is null || IsChecked.Value != toggle.Value)
52 | {
53 | IsChecked.Value ^= true;
54 | FileAction.Command.Execute();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/AppInfra/IpcService.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 |
3 | namespace ADB_Explorer.Services.AppInfra;
4 |
5 | public class IpcService
6 | {
7 | public enum MessageType
8 | {
9 | DragCanceled,
10 | FileMoved,
11 | }
12 |
13 | public static void AcceptIpcMessage(string message)
14 | {
15 | string[] msgContent = message.Split('|');
16 | if (!Enum.TryParse(typeof(MessageType), msgContent[0], true, out var res))
17 | return;
18 |
19 | switch ((MessageType)res)
20 | {
21 | case MessageType.DragCanceled:
22 | if (Enum.TryParse(msgContent[1], out NativeMethods.HResult hr) && hr is NativeMethods.HResult.DRAGDROP_S_CANCEL)
23 | Data.CopyPaste.ClearDrag();
24 | break;
25 | case MessageType.FileMoved:
26 | var content = msgContent[1].Split('\n');
27 | if (Data.CurrentADBDevice.ID != content[0])
28 | return;
29 |
30 | FilePath file = new(content[1]);
31 | if (Data.CurrentPath != file.ParentPath)
32 | return;
33 |
34 | Data.DirList.FileList.RemoveAll(f => f.FullPath == file.FullPath);
35 |
36 | break;
37 | }
38 | }
39 |
40 | public static bool SendIpcMessage(HANDLE hWnd, MessageType type, string content = "")
41 | {
42 | var message = $"{Enum.GetName(type)}|{content}";
43 |
44 | NativeMethods.COPYDATASTRUCT cds = new()
45 | {
46 | dwData = IntPtr.Zero,
47 | cbData = Encoding.Unicode.GetByteCount(message) + 2,
48 | lpData = message
49 | };
50 |
51 | return NativeMethods.SendMessage(hWnd, NativeMethods.WindowMessages.WM_COPYDATA, ref cds);
52 | }
53 |
54 | public static void NotifyDropCancel(NativeMethods.HResult hr)
55 | {
56 | if (Data.RuntimeSettings.DragWithinSlave)
57 | SendIpcMessage(NativeMethods.InterceptMouse.WindowUnderMouse, MessageType.DragCanceled, $"{hr}");
58 | }
59 |
60 | public static void NotifyFileMoved(int remotePid, ADBService.AdbDevice device, FilePath file)
61 | {
62 | var process = Process.GetProcessById(remotePid);
63 |
64 | SendIpcMessage(process.MainWindowHandle, MessageType.FileMoved, $"{device.ID}\n{file.FullPath}");
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/AppInfra/LowLevel/ExplorerWindow.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Helpers;
2 | using ADB_Explorer.Models;
3 | using System.Windows.Automation;
4 |
5 | namespace ADB_Explorer.Services;
6 |
7 | public class ExplorerWindow : IComparable
8 | {
9 | public HANDLE Hwnd { get; }
10 |
11 | private AutomationElement _rootElement = null;
12 | public AutomationElement RootElement
13 | {
14 | get
15 | {
16 | if (_rootElement is null)
17 | {
18 | _rootElement = AutomationElement.FromHandle(Hwnd);
19 | }
20 |
21 | return _rootElement;
22 | }
23 | }
24 |
25 | private AutomationElement _fileList = null;
26 | public AutomationElement FileList
27 | {
28 | get
29 | {
30 | if (_fileList is null)
31 | {
32 | _fileList = RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.List));
33 | }
34 | return _fileList;
35 | }
36 | }
37 |
38 | private Process _process = null;
39 | public Process Process
40 | {
41 | get
42 | {
43 | if (_process is null)
44 | {
45 | // Don't use automation just to get pid if it isn't ready yet
46 | int processId = _fileList is null
47 | ? ProcessHandling.GetProcessIdFromWindowHandle(Hwnd)
48 | : RootElement.Current.ProcessId;
49 |
50 | _process = Process.GetProcessById(processId);
51 | }
52 |
53 | return _process;
54 | }
55 | }
56 |
57 | public string[] Paths { get; }
58 |
59 | ///
60 | /// Gets the resolved file system path based on the current state and context.
61 | ///
62 | /// If multiple paths are available, the method attempts to match using window title.
63 | public string Path
64 | {
65 | get
66 | {
67 | if (Paths.Length == 0)
68 | return null;
69 | else if (Paths.Length == 1)
70 | return Paths[0];
71 | else
72 | // 22H2 with more than one tab
73 | {
74 | var pathDict = Paths.ToDictionary(FileHelper.GetFullName, path => path);
75 |
76 | var query = pathDict.Where(item => RootElement.Current.Name.StartsWith(item.Key));
77 |
78 | return query.Any() ? query.First().Value : null;
79 | }
80 | }
81 | }
82 |
83 | public ExplorerWindow(IGrouping paths)
84 | {
85 | Hwnd = paths.Key;
86 | Paths = [.. paths];
87 | }
88 |
89 | public ExplorerWindow(nint hwnd)
90 | {
91 | Hwnd = hwnd;
92 | }
93 |
94 | public ExplorerWindow(nint hwnd, string path)
95 | {
96 | Hwnd = hwnd;
97 | Paths = [ path ];
98 | }
99 |
100 | public override bool Equals(object obj)
101 | {
102 | return obj is ExplorerWindow window &&
103 | Hwnd.Equals(window.Hwnd);
104 | }
105 |
106 | public override int GetHashCode() => Hwnd.GetHashCode();
107 |
108 | public int CompareTo(object obj) => Hwnd.CompareTo(obj);
109 | }
110 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/AppInfra/LowLevel/FileContentsStream.cs:
--------------------------------------------------------------------------------
1 | // Copied and modified from https://github.com/asklar/clipview under MIT License
2 |
3 | using System.Runtime.InteropServices.ComTypes;
4 |
5 | namespace ADB_Explorer.Services.AppInfra;
6 |
7 | public class FileContentsStream : IDisposable
8 | {
9 | private readonly STATSTG stat;
10 |
11 | private readonly IStream stream;
12 |
13 | public FileContentsStream(IStream stream)
14 | {
15 | this.stream = stream;
16 | stream.Stat(out stat, 0);
17 | }
18 |
19 | public string FileName => stat.pwcsName;
20 | public long Length => stat.cbSize;
21 |
22 | enum STREAM_SEEK
23 | {
24 | STREAM_SEEK_SET,
25 | STREAM_SEEK_CUR,
26 | STREAM_SEEK_END
27 | };
28 |
29 | public void SaveToStream(Stream outputStream)
30 | {
31 | // Initialize the buffer to the size of the stream.
32 | // This should work as long as we are able to create a buffer of such size.
33 | byte[] buffer = new byte[stat.cbSize];
34 | stream.Seek(0, (int)STREAM_SEEK.STREAM_SEEK_SET, HANDLE.Zero);
35 |
36 | HANDLE pcbRead = Marshal.AllocHGlobal(sizeof(int));
37 | try
38 | {
39 | stream.Read(buffer, buffer.Length, pcbRead);
40 | outputStream.Write(buffer, 0, Marshal.ReadInt32(pcbRead));
41 | }
42 | catch (EndOfStreamException)
43 | { }
44 | finally
45 | {
46 | Marshal.FreeHGlobal(pcbRead);
47 | }
48 | }
49 |
50 | public void Save(string filepath, bool disposeAfter = true)
51 | {
52 | using var file = File.Create(filepath);
53 | SaveToStream(file);
54 |
55 | if (disposeAfter)
56 | Dispose();
57 | }
58 |
59 | public void Dispose()
60 | {
61 | Marshal.ReleaseComObject(stream);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/AppInfra/LowLevel/MonitorInfo.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 |
3 | namespace ADB_Explorer.Services;
4 |
5 | public static partial class NativeMethods
6 | {
7 | public static class MonitorInfo
8 | {
9 | private enum MonitorType
10 | {
11 | Primary = 0x00000001,
12 | Nearest = 0x00000002,
13 | }
14 |
15 | private static HANDLE? mainWinHandle;
16 | private static HANDLE primaryMonitor => PrimaryMonitor();
17 |
18 | public static void Init(Window window)
19 | {
20 | mainWinHandle ??= new WindowInteropHelper(window).EnsureHandle();
21 | }
22 |
23 | public static bool? IsPrimaryMonitor(Window window)
24 | {
25 | Init(window);
26 | return IsPrimaryMonitor();
27 | }
28 |
29 | public static bool? IsPrimaryMonitor()
30 | {
31 | if (mainWinHandle is null)
32 | return null;
33 |
34 | var current = NearestMonitor(mainWinHandle.Value);
35 |
36 | return current == primaryMonitor;
37 | }
38 |
39 | public static HANDLE NearestMonitor(HANDLE handle) => MonitorFromWindow(handle, MonitorType.Nearest);
40 |
41 | public static HANDLE PrimaryMonitor() => MonitorFromWindow(IntPtr.Zero, MonitorType.Primary);
42 |
43 | public static POINT MousePositionToDpi(POINT mousePosition, HANDLE hWnd)
44 | {
45 | // Get the DPI for this window
46 | var dpi = GetDpiForWindow(hWnd);
47 | if (dpi == 0) // fallback to default DPI if window not found
48 | dpi = 96;
49 |
50 | // Calculate the scaling factor (96 is the default DPI)
51 | Data.RuntimeSettings.DpiScalingFactor = 96f / dpi;
52 |
53 | // Convert the coordinates
54 | return new(
55 | (int)(mousePosition.X * Data.RuntimeSettings.DpiScalingFactor),
56 | (int)(mousePosition.Y * Data.RuntimeSettings.DpiScalingFactor));
57 | }
58 |
59 | [DllImport("User32.dll")]
60 | private static extern HANDLE MonitorFromWindow(HANDLE hwnd, MonitorType dwFlags);
61 |
62 | [DllImport("User32.dll")]
63 | static extern uint GetDpiForWindow(HANDLE hwnd);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/AppInfra/LowLevel/ProcessHandling.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 |
3 | namespace ADB_Explorer.Services;
4 |
5 | public class ProcessHandling
6 | {
7 | public static void KillProcess(Process process, bool recursive = true)
8 | {
9 | var procs = GetChildProcesses(process, recursive);
10 |
11 | foreach (var item in procs)
12 | {
13 | item.Kill();
14 | }
15 | }
16 |
17 | public static IEnumerable GetChildProcesses(Process process, bool recursive = true)
18 | {
19 | ManagementObjectSearcher searcher;
20 | try
21 | {
22 | searcher = new(
23 | "SELECT * " +
24 | "FROM Win32_Process " +
25 | "WHERE ParentProcessId=" + process.Id);
26 | }
27 | catch
28 | {
29 | // if we can't get the pid without throwing an exception, the process is useless
30 | yield break;
31 | }
32 |
33 | foreach (var item in searcher.Get())
34 | {
35 | Process proc;
36 |
37 | try
38 | {
39 | proc = Process.GetProcessById((int)(uint)item["ProcessId"]);
40 | }
41 | catch (Exception)
42 | {
43 | continue;
44 | }
45 |
46 | if (recursive)
47 | {
48 | foreach (var subItem in GetChildProcesses(proc))
49 | {
50 | yield return subItem;
51 | }
52 | }
53 | else
54 | yield return proc;
55 | }
56 |
57 | yield return process;
58 | }
59 |
60 | public static IEnumerable GetConflictingApps()
61 | => Process.GetProcesses()
62 | .Where(p => AdbExplorerConst.INCOMPATIBLE_APPS.Contains(p.ProcessName))
63 | .Select(p => p.ProcessName);
64 |
65 | public static int GetProcessIdFromWindowHandle(HANDLE hwnd)
66 | {
67 | GetWindowThreadProcessId(hwnd, out uint processId);
68 | return (int)processId;
69 | }
70 |
71 | [DllImport("User32.dll", SetLastError = true)]
72 | private static extern uint GetWindowThreadProcessId(HANDLE hWnd, out uint lpdwProcessId);
73 | }
74 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/AppInfra/LowLevel/ThemeService.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.ViewModels;
2 |
3 | namespace ADB_Explorer.Services;
4 |
5 | internal class ThemeService : ViewModelBase
6 | {
7 | //https://medium.com/southworks/handling-dark-light-modes-in-wpf-3f89c8a4f2db
8 |
9 | private const string RegistryKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
10 | private const string RegistryValueName = "AppsUseLightTheme";
11 | private const string QueryPrefix = "SELECT * FROM RegistryValueChangeEvent WHERE Hive = 'HKEY_USERS' AND KeyPath";
12 |
13 | private AppSettings.AppTheme? windowsTheme;
14 | public AppSettings.AppTheme WindowsTheme
15 | {
16 | get
17 | {
18 | if (windowsTheme is null)
19 | WatchTheme();
20 |
21 | return windowsTheme.Value;
22 | }
23 | set => Set(ref windowsTheme, value);
24 | }
25 |
26 | public void WatchTheme()
27 | {
28 | var currentUser = WindowsIdentity.GetCurrent();
29 | string query = $@"{QueryPrefix} = '{currentUser.User.Value}\\{RegistryKeyPath.Replace(@"\", @"\\")}' AND ValueName = '{RegistryValueName}'";
30 |
31 | // This can fail on Windows 7, but we do not support
32 | ManagementEventWatcher watcher = new(query);
33 | watcher.EventArrived += (sender, args) =>
34 | {
35 | WindowsTheme = GetWindowsTheme();
36 | };
37 |
38 | watcher.Start();
39 |
40 | WindowsTheme = GetWindowsTheme();
41 | }
42 |
43 | private static AppSettings.AppTheme GetWindowsTheme()
44 | {
45 | using var key = Registry.CurrentUser.OpenSubKey(RegistryKeyPath);
46 | return key?.GetValue(RegistryValueName) is < 1 ? AppSettings.AppTheme.dark : AppSettings.AppTheme.light;
47 | }
48 |
49 | public ApplicationTheme AppThemeToActual(AppSettings.AppTheme appTheme) => appTheme switch
50 | {
51 | AppSettings.AppTheme.light => ApplicationTheme.Light,
52 | AppSettings.AppTheme.dark => ApplicationTheme.Dark,
53 | AppSettings.AppTheme.windowsDefault => AppThemeToActual(WindowsTheme),
54 | _ => throw new NotSupportedException(),
55 | };
56 |
57 | public void SetTheme(AppSettings.AppTheme theme) => SetTheme(AppThemeToActual(theme));
58 |
59 | public static void SetTheme(ApplicationTheme theme) => App.Current.Dispatcher.Invoke(() =>
60 | {
61 | ThemeManager.Current.ApplicationTheme = theme;
62 |
63 | Task.Run(() =>
64 | {
65 | var keys = ((ResourceDictionary)Application.Current.Resources["DynamicBrushes"]).Keys;
66 | string[] brushes = new string[keys.Count];
67 | keys.CopyTo(brushes, 0);
68 |
69 | Parallel.ForEach(brushes, (brush) => SetResourceColor(theme, brush));
70 | });
71 | });
72 |
73 | public static void SetResourceColor(ApplicationTheme theme, string resource)
74 | {
75 | App.Current.Dispatcher.Invoke(() => Application.Current.Resources[resource] = new SolidColorBrush((Color)Application.Current.Resources[$"{theme}{resource}"]));
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/AppInfra/LowLevel/WindowStyle.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Services;
2 |
3 | public static class WindowStyle
4 | {
5 | public static void SetWindowHidden(HANDLE hwnd)
6 | {
7 | var style = GetWindowLong(hwnd, NativeMethods.WindowIndex.GWL_EXSTYLE)
8 | | NativeMethods.ExtendedWindowStyle.WS_EX_TOOLWINDOW
9 | | NativeMethods.ExtendedWindowStyle.WS_EX_NOACTIVATE;
10 |
11 | SetWindowLong(hwnd, NativeMethods.WindowIndex.GWL_EXSTYLE, style);
12 | }
13 |
14 | [DllImport("user32.dll")]
15 | private static extern NativeMethods.ExtendedWindowStyle GetWindowLong(HANDLE hWnd, NativeMethods.WindowIndex nIndex);
16 |
17 |
18 | [DllImport("user32.dll")]
19 | private static extern int SetWindowLong(HANDLE hWnd, NativeMethods.WindowIndex nIndex, NativeMethods.ExtendedWindowStyle dwNewLong);
20 | }
21 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/AppInfra/Network.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 | using System.Net.Http;
3 | using System.Net.NetworkInformation;
4 |
5 | namespace ADB_Explorer.Services;
6 |
7 | public static class Network
8 | {
9 | private static readonly HttpClient Client = new();
10 |
11 | public static async Task GetRequestAsync(Uri url)
12 | {
13 | try
14 | {
15 | return await Client.GetStringAsync(url);
16 | }
17 | catch (Exception)
18 | {
19 | return null;
20 | }
21 | }
22 |
23 | public static async Task LatestAppReleaseAsync()
24 | {
25 | Client.DefaultRequestHeaders.Add("User-Agent", "Unity web player");
26 |
27 | var response = await GetRequestAsync(Resources.Links.REPO_RELEASES_URL);
28 | if (response is null)
29 | return null;
30 |
31 | JArray json = (JArray)JsonConvert.DeserializeObject(response);
32 |
33 | if (!json.HasValues)
34 | return null;
35 |
36 | var ver = json[0]["tag_name"].ToString().TrimStart('v');
37 | return new(ver);
38 | }
39 |
40 | public static string GetWsaIp()
41 | {
42 | var wsaInterface = NetworkInterface.GetAllNetworkInterfaces().Where(net => net.Name.Contains(AdbExplorerConst.WSA_INTERFACE_NAME));
43 | if (!wsaInterface.Any())
44 | return null;
45 |
46 | var addresses = wsaInterface.First().GetIPProperties().UnicastAddresses;
47 | if (!addresses.Any())
48 | return null;
49 |
50 | var ipv4 = addresses.Where(add => add.Address.AddressFamily is System.Net.Sockets.AddressFamily.InterNetwork);
51 | if (!ipv4.Any())
52 | return null;
53 |
54 | return ipv4.First().Address.ToString();
55 | }
56 |
57 | public static string GetDefaultBrowser()
58 | {
59 | try
60 | {
61 | var browserName = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice");
62 | var browserCommand = Registry.ClassesRoot.OpenSubKey($@"{browserName.GetValue("Progid")}\shell\open\command").GetValue(null);
63 | return AdbRegEx.RE_EXE_FROM_REG().Match($"{browserCommand}").Value;
64 | }
65 | catch
66 | {
67 | return null;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/AppInfra/Storage.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Services;
2 |
3 | public static class Storage
4 | {
5 | public static object RetrieveValue(Enum key) => RetrieveValue(key.ToString());
6 |
7 | public static object RetrieveValue(string key)
8 | {
9 | return Application.Current.Properties[key];
10 | }
11 |
12 | public static T Retrieve(string key)
13 | {
14 | return (T)Application.Current.Properties[key];
15 | }
16 |
17 | public static void StoreValue(Enum key, object value) => StoreValue(key.ToString(), value);
18 |
19 | public static void StoreValue(string key, object value)
20 | {
21 | Application.Current.Properties[key] = value;
22 | }
23 |
24 | public static object RetrieveEnum(Type type) => Application.Current.Properties[type.ToString()];
25 | public static object RetrieveEnum(string key) => Application.Current.Properties[key];
26 |
27 | public static T RetrieveEnum(string key = "") => RetrieveEnum(string.IsNullOrEmpty(key) ? typeof(T).ToString() : key) switch
28 | {
29 | string strVal => (T)Enum.Parse(typeof(T), strVal),
30 | long longVal => (T)Enum.ToObject(typeof(T), longVal),
31 | _ => default
32 | };
33 |
34 | public static void StoreEnum(Enum value)
35 | {
36 | Application.Current.Properties[value.GetType().ToString()] = value;
37 | }
38 |
39 | public static bool? RetrieveBool(Enum value) => RetrieveBool(value.ToString());
40 |
41 | public static bool? RetrieveBool(string key)
42 | {
43 | return Application.Current?.Properties[key] switch
44 | {
45 | string value when !string.IsNullOrEmpty(value) => bool.Parse(value),
46 | bool val => val,
47 | _ => null
48 | };
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/FileOperation/FileArchiveOperation.cs:
--------------------------------------------------------------------------------
1 | //namespace ADB_Explorer.Services;
2 |
3 | //public class FileArchiveOperation : AbstractShellFileOperation
4 | //{
5 | // // tar -cz /sdcard/Download > /sdcard/Download/arch.tar.gz
6 | //}
7 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/FileOperation/FileChangeModifiedOperation.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 | using ADB_Explorer.ViewModels;
3 |
4 | namespace ADB_Explorer.Services;
5 |
6 | public class FileChangeModifiedOperation : AbstractShellFileOperation
7 | {
8 | public readonly DateTime NewDate;
9 |
10 | public FileChangeModifiedOperation(FileClass filePath, DateTime newDate, ADBService.AdbDevice adbDevice, Dispatcher dispatcher)
11 | : base(filePath, adbDevice, dispatcher)
12 | {
13 | OperationName = OperationType.Update;
14 | NewDate = newDate;
15 | }
16 |
17 | public override void Start()
18 | {
19 | if (Status == OperationStatus.InProgress)
20 | {
21 | throw new Exception("Cannot start an already active operation!");
22 | }
23 |
24 | Status = OperationStatus.InProgress;
25 | StatusInfo = new InProgShellProgressViewModel();
26 |
27 | var operationTask = ADBService.ExecuteVoidShellCommand(Device.ID,
28 | CancelTokenSource.Token,
29 | "touch",
30 | "-m",
31 | "-t",
32 | NewDate.ToString("yyyyMMddHHmm.ss"),
33 | ADBService.EscapeAdbShellString(FilePath.FullPath));
34 |
35 | operationTask.ContinueWith((t) =>
36 | {
37 | if (t.Result == "")
38 | {
39 | Status = OperationStatus.Completed;
40 | StatusInfo = new CompletedShellProgressViewModel();
41 | }
42 | else
43 | {
44 | Status = OperationStatus.Failed;
45 | StatusInfo = new FailedOpProgressViewModel(t.Result);
46 | }
47 |
48 | }, TaskContinuationOptions.OnlyOnRanToCompletion);
49 |
50 | operationTask.ContinueWith((t) =>
51 | {
52 | Status = OperationStatus.Canceled;
53 | StatusInfo = new CanceledOpProgressViewModel();
54 | }, TaskContinuationOptions.OnlyOnCanceled);
55 |
56 | operationTask.ContinueWith((t) =>
57 | {
58 | Status = OperationStatus.Failed;
59 | StatusInfo = new FailedOpProgressViewModel(t.Exception.InnerException.Message);
60 | }, TaskContinuationOptions.OnlyOnFaulted);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/FileOperation/FileDeleteOperation.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Converters;
2 | using ADB_Explorer.Models;
3 | using ADB_Explorer.ViewModels;
4 |
5 | namespace ADB_Explorer.Services;
6 |
7 | public class FileDeleteOperation : AbstractShellFileOperation
8 | {
9 | public FileDeleteOperation(Dispatcher dispatcher, ADBService.AdbDevice adbDevice, FileClass path)
10 | : base(path, adbDevice, dispatcher)
11 | {
12 | OperationName = OperationType.Delete;
13 | AltTarget = NavHistory.SpecialLocation.devNull;
14 | }
15 |
16 | public override void Start()
17 | {
18 | if (Status == OperationStatus.InProgress)
19 | {
20 | throw new Exception("Cannot start an already active operation!");
21 | }
22 |
23 | Status = OperationStatus.InProgress;
24 | StatusInfo = new InProgShellProgressViewModel();
25 |
26 | var task = ADBService.ExecuteVoidShellCommand(Device.ID, CancelTokenSource.Token, "rm", "-rf", ADBService.EscapeAdbShellString(FilePath.FullPath));
27 |
28 | task.ContinueWith((t) =>
29 | {
30 | if (t.Result == "")
31 | {
32 | Status = OperationStatus.Completed;
33 | StatusInfo = new CompletedShellProgressViewModel();
34 | }
35 | else
36 | {
37 | Status = OperationStatus.Failed;
38 | var res = AdbRegEx.RE_SHELL_ERROR().Matches(t.Result);
39 | var updates = res.Where(m => m.Success).Select(m => new ShellErrorInfo(m, base.FilePath.FullPath));
40 | base.AddUpdates(updates);
41 |
42 | var message = updates.Any() ? updates.Last().Message : "";
43 | if (message.Contains(':'))
44 | message = message.Split(':').Last().TrimStart();
45 |
46 | var errorString = FileOpStatusConverter.StatusString(typeof(ShellErrorInfo),
47 | failed: Children.Count > 0 ? updates.Count() : -1,
48 | message: message,
49 | total: true);
50 |
51 | StatusInfo = new FailedOpProgressViewModel(errorString);
52 | }
53 |
54 | }, TaskContinuationOptions.OnlyOnRanToCompletion);
55 |
56 | task.ContinueWith((t) =>
57 | {
58 | Status = OperationStatus.Canceled;
59 | StatusInfo = new CanceledOpProgressViewModel();
60 | }, TaskContinuationOptions.OnlyOnCanceled);
61 |
62 | task.ContinueWith((t) =>
63 | {
64 | Status = OperationStatus.Failed;
65 | StatusInfo = new FailedOpProgressViewModel(t.Exception.InnerException.Message);
66 | }, TaskContinuationOptions.OnlyOnFaulted);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/ADB Explorer/Services/FileOperation/FileRenameOperation.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 | using ADB_Explorer.ViewModels;
3 |
4 | namespace ADB_Explorer.Services;
5 |
6 | public class FileRenameOperation : AbstractShellFileOperation
7 | {
8 | public FileRenameOperation(FileClass filePath, string targetPath, ADBService.AdbDevice adbDevice, Dispatcher dispatcher)
9 | : base(new(filePath), adbDevice, dispatcher)
10 | {
11 | OperationName = OperationType.Rename;
12 |
13 | TargetPath = new(targetPath, FilePath.Type);
14 | }
15 |
16 | public override void Start()
17 | {
18 | if (Status == OperationStatus.InProgress)
19 | {
20 | throw new Exception("Cannot start an already active operation!");
21 | }
22 |
23 | Status = OperationStatus.InProgress;
24 | StatusInfo = new InProgShellProgressViewModel();
25 | CancelTokenSource = new();
26 |
27 | var operationTask = ADBService.ExecuteVoidShellCommand(Device.ID,
28 | CancelTokenSource.Token,
29 | "mv",
30 | ADBService.EscapeAdbShellString(FilePath.FullPath),
31 | ADBService.EscapeAdbShellString(TargetPath.FullPath));
32 |
33 | operationTask.ContinueWith((t) =>
34 | {
35 | if (t.Result == "")
36 | {
37 | Status = OperationStatus.Completed;
38 | StatusInfo = new CompletedShellProgressViewModel();
39 | }
40 | else
41 | {
42 | Status = OperationStatus.Failed;
43 | StatusInfo = new FailedOpProgressViewModel(t.Result);
44 | }
45 |
46 | }, TaskContinuationOptions.OnlyOnRanToCompletion);
47 |
48 | operationTask.ContinueWith((t) =>
49 | {
50 | Status = OperationStatus.Canceled;
51 | StatusInfo = new CanceledOpProgressViewModel();
52 | }, TaskContinuationOptions.OnlyOnCanceled);
53 |
54 | operationTask.ContinueWith((t) =>
55 | {
56 | Status = OperationStatus.Failed;
57 | StatusInfo = new FailedOpProgressViewModel(t.Exception.InnerException.Message);
58 | }, TaskContinuationOptions.OnlyOnFaulted);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/ADB Explorer/Styles/FileOpColumn.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
13 |
14 |
19 |
28 |
29 |
30 |
37 |
--------------------------------------------------------------------------------
/ADB Explorer/Usings.cs:
--------------------------------------------------------------------------------
1 | global using Microsoft.Win32;
2 | global using Microsoft.WindowsAPICodePack.Dialogs;
3 | global using ModernWpf;
4 | global using ModernWpf.Controls;
5 | global using ModernWpf.Controls.Primitives;
6 | global using Newtonsoft.Json;
7 | global using Newtonsoft.Json.Linq;
8 | global using System;
9 | global using System.Collections.Concurrent;
10 | global using System.Collections.Generic;
11 | global using System.Collections.ObjectModel;
12 | global using System.Collections.Specialized;
13 | global using System.ComponentModel;
14 | global using System.Diagnostics;
15 | global using System.Diagnostics.CodeAnalysis;
16 | global using System.Globalization;
17 | global using System.IO;
18 | global using System.IO.IsolatedStorage;
19 | global using System.Linq;
20 | global using System.Management;
21 | global using System.Reflection;
22 | global using System.Runtime.CompilerServices;
23 | global using System.Runtime.InteropServices;
24 | global using System.Security.Cryptography;
25 | global using System.Security.Principal;
26 | global using System.Text;
27 | global using System.Text.RegularExpressions;
28 | global using System.Threading;
29 | global using System.Threading.Tasks;
30 | global using System.Windows;
31 | global using System.Windows.Controls;
32 | global using System.Windows.Controls.Primitives;
33 | global using System.Windows.Data;
34 | global using System.Windows.Input;
35 | global using System.Windows.Interop;
36 | global using System.Windows.Media;
37 | global using System.Windows.Media.Imaging;
38 | global using System.Windows.Shell;
39 | global using System.Windows.Threading;
40 |
41 | global using HANDLE = nint;
42 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/Device/DeviceAction.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Helpers;
2 | using ADB_Explorer.Services;
3 |
4 | namespace ADB_Explorer.ViewModels;
5 |
6 | public class DeviceAction : BaseAction
7 | {
8 | public string Description { get; }
9 |
10 | public DeviceAction(Func canExecute, Action action, string description = null)
11 | : base(canExecute, action)
12 | {
13 | Description = description;
14 | }
15 |
16 | public override string ToString()
17 | {
18 | return Description;
19 | }
20 | }
21 |
22 | public class RebootCommand : DeviceAction
23 | {
24 | public enum RebootType
25 | {
26 | Title,
27 | Regular,
28 | Bootloader,
29 | Recovery,
30 | Sideload,
31 | SideloadAuto,
32 | }
33 |
34 | public RebootCommand(LogicalDeviceViewModel device, RebootType type)
35 | : base(() => type is not RebootType.Title,
36 | () => Task.Run(() => ADBService.AdbDevice.Reboot(device.ID, RebootParam(type))),
37 | RebootString(type))
38 | { }
39 |
40 | private static string RebootParam(RebootType type) => type switch
41 | {
42 | RebootType.Regular => "",
43 | RebootType.Bootloader => "bootloader",
44 | RebootType.Recovery => "recovery",
45 | RebootType.Sideload => "sideload",
46 | RebootType.SideloadAuto => "sideload-auto-reboot",
47 | _ => throw new NotSupportedException(),
48 | };
49 |
50 | private static string RebootString(RebootType type) => type switch
51 | {
52 | RebootType.Title => Strings.Resources.S_DEVICE_REBOOT_TITLE,
53 | RebootType.Regular => Strings.Resources.S_REBOOT_SYSTEM,
54 | RebootType.Bootloader => Strings.Resources.S_REBOOT_BOOTLOADER,
55 | RebootType.Recovery => Strings.Resources.S_RECOVERY_MODE,
56 | RebootType.Sideload => Strings.Resources.S_REBOOT_SIDELOAD,
57 | RebootType.SideloadAuto => Strings.Resources.S_REBOOT_SIDELOAD_AUTO,
58 | _ => throw new NotSupportedException(),
59 | };
60 | }
61 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/Device/HistoryDeviceViewModel.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Helpers;
2 | using ADB_Explorer.Models;
3 |
4 | namespace ADB_Explorer.ViewModels;
5 |
6 | public class HistoryDeviceViewModel : NewDeviceViewModel
7 | {
8 | private HistoryDevice device;
9 | protected new HistoryDevice Device
10 | {
11 | get => device;
12 | set => Set(ref device, value);
13 | }
14 |
15 | #region Read only properties
16 |
17 | public string DeviceName => Device.DeviceName;
18 |
19 | public override string Tooltip => Strings.Resources.S_DEVICE_SAVED;
20 |
21 | public override bool DeviceExists => false;
22 |
23 | public bool IsDeviceNameValid => !string.IsNullOrEmpty(DeviceName);
24 |
25 | #endregion
26 |
27 | public DeviceAction RemoveCommand { get; }
28 |
29 | public HistoryDeviceViewModel(HistoryDevice device) : base(device)
30 | {
31 | Device = device;
32 |
33 | RemoveCommand = DeviceHelper.RemoveDeviceCommand(this);
34 | }
35 |
36 | public static HistoryDeviceViewModel New(NewDeviceViewModel device)
37 | {
38 | return new(new HistoryDevice()
39 | {
40 | IpAddress = device.IsIpAddressValid ? device.IpAddress : null,
41 | HostName = device.IsIpAddressValid ? null : device.HostName,
42 | ConnectPort = device.ConnectPort
43 | });
44 | }
45 |
46 | public static HistoryDeviceViewModel New(StorageDevice device)
47 | {
48 | HistoryDeviceViewModel historyDevice = new(new HistoryDevice()
49 | {
50 | DeviceName = device.DeviceName,
51 | IpAddress = device.IpAddress,
52 | ConnectPort = device.ConnectPort
53 | });
54 |
55 | if (!historyDevice.IsIpAddressValid)
56 | {
57 | historyDevice.HostName = historyDevice.IpAddress;
58 | }
59 |
60 | return historyDevice;
61 | }
62 |
63 | public StorageDevice GetStorage() => new(this);
64 |
65 | public bool SetDeviceName(string name)
66 | {
67 | if (DeviceName != name)
68 | {
69 | Device.DeviceName = name;
70 |
71 | return true;
72 | }
73 |
74 | return false;
75 | }
76 | }
77 |
78 | public class StorageDevice
79 | {
80 | public string DeviceName { get; private set; }
81 | public string IpAddress { get; private set; }
82 | public string ConnectPort { get; private set; }
83 |
84 | public StorageDevice(HistoryDeviceViewModel device)
85 | {
86 | DeviceName = device.DeviceName;
87 | IpAddress = device.IsIpAddressValid ? device.IpAddress : device.HostName;
88 | ConnectPort = device.ConnectPort;
89 | }
90 |
91 | [JsonConstructor]
92 | public StorageDevice(string deviceName, string ipAddress, string connectPort)
93 | {
94 | DeviceName = deviceName;
95 | IpAddress = ipAddress;
96 | ConnectPort = connectPort;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/Device/WsaPkgDeviceViewModel.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Helpers;
2 | using ADB_Explorer.Models;
3 |
4 | namespace ADB_Explorer.ViewModels;
5 |
6 | public class WsaPkgDeviceViewModel : DeviceViewModel
7 | {
8 | private WsaPkgDevice device;
9 | protected new WsaPkgDevice Device
10 | {
11 | get => device;
12 | set => Set(ref device, value);
13 | }
14 |
15 | public DateTime LastLaunch => Device.LastLaunch;
16 |
17 | public DeviceAction LaunchWsaCommand { get; }
18 |
19 | public override string Tooltip => Strings.Resources.S_WSA_PKG_TIP;
20 |
21 | public override bool DeviceExists => false;
22 |
23 | public WsaPkgDeviceViewModel(WsaPkgDevice device) : base(device)
24 | {
25 | Device = device;
26 |
27 | LaunchWsaCommand = DeviceHelper.LaunchWsa(this);
28 | }
29 |
30 | public void SetLastLaunch(DateTime? newDate = null)
31 | {
32 | Device.LastLaunch = newDate is null ? DateTime.Now : newDate.Value;
33 | OnPropertyChanged(nameof(LastLaunch));
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/Drive/DriveViewModel.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Helpers;
2 | using ADB_Explorer.Models;
3 | using ADB_Explorer.Services;
4 |
5 | namespace ADB_Explorer.ViewModels;
6 |
7 | public class DriveViewModel : AbstractDrive
8 | {
9 | #region Full properties
10 |
11 | private Drive drive;
12 | public Drive Drive
13 | {
14 | get => drive;
15 | set => Set(ref drive, value);
16 | }
17 |
18 | private bool driveSelected = false;
19 | public bool DriveSelected
20 | {
21 | get => driveSelected;
22 | set => Set(ref driveSelected, value);
23 | }
24 |
25 | private bool driveEnabled = true;
26 | public bool DriveEnabled
27 | {
28 | get => driveEnabled;
29 | protected set => Set(ref driveEnabled, value);
30 | }
31 |
32 | #endregion
33 |
34 | #region Read only properties
35 |
36 | public string Path => Drive.Path;
37 | public new DriveType Type => Drive.Type;
38 | public bool IsFUSE => Drive.IsFUSE;
39 |
40 | public new string DisplayName => Drive.DisplayName;
41 |
42 | public string DriveIcon => Type switch
43 | {
44 | DriveType.Root => "\uF259",
45 | DriveType.Internal => "\uEDA2",
46 | DriveType.Expansion => "\uE7F1",
47 | DriveType.External => "\uE88E",
48 | DriveType.Unknown => null,
49 | DriveType.Emulated => "\uEDA2",
50 | DriveType.Trash => "\uE74D",
51 | DriveType.Temp => "\uE912",
52 | DriveType.Package => "\uE7B8",
53 | _ => throw new NotImplementedException(),
54 | };
55 |
56 | #endregion
57 |
58 | #region Commands
59 |
60 | public BaseAction BrowseCommand { get; private set; }
61 | public BaseAction SelectCommand { get; private set; }
62 |
63 | #endregion
64 |
65 | public DriveViewModel(Drive drive)
66 | {
67 | Drive = drive;
68 |
69 | BrowseCommand = new(() => true, () => Data.RuntimeSettings.BrowseDrive = this);
70 | SelectCommand = new(() => true, () => DriveSelected = true);
71 |
72 | Data.RuntimeSettings.PropertyChanged += RuntimeSettings_PropertyChanged;
73 | }
74 |
75 | private void RuntimeSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
76 | {
77 | if (e.PropertyName == nameof(AppRuntimeSettings.CollapseDrives) && Data.RuntimeSettings.CollapseDrives)
78 | {
79 | DriveSelected = false;
80 | }
81 | }
82 |
83 | public void SetType(DriveType type)
84 | {
85 | if (Drive.Type != type)
86 | {
87 | Drive.Type = type;
88 | OnPropertyChanged(nameof(Type));
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/Drive/LogicalDriveViewModel.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 |
3 | namespace ADB_Explorer.ViewModels;
4 |
5 | class LogicalDriveViewModel : DriveViewModel
6 | {
7 | private LogicalDrive drive;
8 | protected new LogicalDrive Drive
9 | {
10 | get => drive;
11 | set => Set(ref drive, value);
12 | }
13 |
14 | public string Size => Drive.Size;
15 | public string Used => Drive.Used;
16 | public string Available => Drive.Available;
17 | public sbyte UsageP => Drive.UsageP;
18 |
19 | public bool UsageWarning => UsageP >= AdbExplorerConst.DRIVE_WARNING;
20 | public string ID => Drive.ID;
21 |
22 |
23 | public LogicalDriveViewModel(LogicalDrive drive) : base(drive)
24 | {
25 | Drive = drive;
26 | }
27 |
28 | public void UpdateDrive(LogicalDrive other)
29 | {
30 | if (Drive.Size != other.Size)
31 | {
32 | Drive.Size = other.Size;
33 | OnPropertyChanged(nameof(Size));
34 | }
35 |
36 | if (Drive.Used != other.Used)
37 | {
38 | Drive.Used = other.Used;
39 | OnPropertyChanged(nameof(Used));
40 | }
41 |
42 | if (Drive.Available != other.Available)
43 | {
44 | Drive.Available = other.Available;
45 | OnPropertyChanged(nameof(Available));
46 | }
47 |
48 | if (Drive.UsageP != other.UsageP)
49 | {
50 | Drive.UsageP = other.UsageP;
51 | OnPropertyChanged(nameof(UsageP));
52 | }
53 |
54 | if (Drive.FileSystem != other.FileSystem)
55 | {
56 | Drive.FileSystem = other.FileSystem;
57 | OnPropertyChanged(nameof(IsFUSE));
58 | }
59 | }
60 |
61 | public void SetExtension(bool isMMC = true) => SetType(isMMC ? DriveType.Expansion : DriveType.External);
62 |
63 | public override string ToString() => DisplayName is null ? ID : DisplayName;
64 | }
65 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/Drive/VirtualDriveViewModel.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 |
3 | namespace ADB_Explorer.ViewModels;
4 |
5 | class VirtualDriveViewModel : DriveViewModel
6 | {
7 | private VirtualDrive drive;
8 | protected new VirtualDrive Drive
9 | {
10 | get => drive;
11 | set => Set(ref drive, value);
12 | }
13 |
14 | public long? ItemsCount => Drive.ItemsCount;
15 |
16 |
17 | public VirtualDriveViewModel(VirtualDrive drive) : base(drive)
18 | {
19 | Drive = drive;
20 | }
21 |
22 | public void SetItemsCount(int? count) => SetItemsCount((long?)count);
23 |
24 | public void SetItemsCount(long? newCount)
25 | {
26 | if (Drive.ItemsCount != newCount)
27 | {
28 | Drive.ItemsCount = newCount;
29 | OnPropertyChanged(nameof(ItemsCount));
30 | }
31 |
32 | DriveEnabled = ItemsCount != -1;
33 | }
34 |
35 | public override string ToString() => $"{Type}";
36 | }
37 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/FileOp/CanceledOpProgressViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.ViewModels;
2 |
3 | internal class CanceledOpProgressViewModel : FileOpProgressViewModel
4 | {
5 | public CanceledOpProgressViewModel() : base(Services.FileOperation.OperationStatus.Canceled)
6 | {
7 |
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/FileOp/CompletedShellProgressViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.ViewModels;
2 |
3 | internal class CompletedShellProgressViewModel : FileOpProgressViewModel
4 | {
5 | public string Message { get; }
6 |
7 | public CompletedShellProgressViewModel(string message = "Completed") : base(Services.FileOperation.OperationStatus.Completed)
8 | {
9 | Message = message;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/FileOp/CompletedSyncProgressViewModel.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Converters;
2 | using ADB_Explorer.Services;
3 |
4 | namespace ADB_Explorer.ViewModels;
5 |
6 | public class CompletedSyncProgressViewModel : FileOpProgressViewModel
7 | {
8 | private readonly AdbSyncStatsInfo adbInfo;
9 |
10 | public CompletedSyncProgressViewModel(AdbSyncStatsInfo adbInfo) : base(FileOperation.OperationStatus.Completed)
11 | {
12 | this.adbInfo = adbInfo;
13 | }
14 |
15 | public UInt64 FilesTransferred => adbInfo.FilesTransferred;
16 |
17 | public UInt64 FilesSkipped => adbInfo.FilesSkipped;
18 |
19 | public decimal? AverageRateMBps => adbInfo.AverageRate;
20 |
21 | public UInt64? TotalBytes => adbInfo.TotalBytes;
22 |
23 | public decimal? TotalSeconds => adbInfo.TotalTime;
24 |
25 | public int FileCountCompletedRate => (int)((float)FilesTransferred / (FilesTransferred + FilesSkipped) * 100.0);
26 |
27 | public string FileCountCompletedString => $"{FilesTransferred} of {FilesTransferred + FilesSkipped}";
28 |
29 | public string AverageRateString => AverageRateMBps.HasValue ? $"{UnitConverter.ToSize((UInt64)(AverageRateMBps.Value * 1024 * 1024))}/s" : string.Empty;
30 |
31 | public string TotalSize => TotalBytes.HasValue ? UnitConverter.ToSize(TotalBytes.Value) : string.Empty;
32 |
33 | public string TotalTime => TotalSeconds.HasValue ? UnitConverter.ToTime(TotalSeconds.Value) : string.Empty;
34 | }
35 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/FileOp/FailedOpProgressViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.ViewModels;
2 |
3 | public class FailedOpProgressViewModel : FileOpProgressViewModel
4 | {
5 | public string Error { get; }
6 |
7 | public FailedOpProgressViewModel(string error) : base(Services.FileOperation.OperationStatus.Failed)
8 | {
9 | error = error.TrimEnd('\r', '\n');
10 |
11 | var firstDoubleSlash = error.StartsWith(@"\\");
12 | error = string.Join(@"\", error.Split(@"\\"));
13 | if (firstDoubleSlash)
14 | error = @"\\" + error;
15 |
16 | Error = error;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/FileOp/FileOpProgressViewModel.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Models;
2 |
3 | namespace ADB_Explorer.ViewModels;
4 |
5 | public abstract class FileOpProgressViewModel : ViewModelBase
6 | {
7 | public Services.FileOperation.OperationStatus Status { get; }
8 |
9 | private FileOpFilter.FilterType FilterType => Status switch
10 | {
11 | Services.FileOperation.OperationStatus.Waiting => FileOpFilter.FilterType.Pending,
12 | Services.FileOperation.OperationStatus.InProgress => FileOpFilter.FilterType.Running,
13 | Services.FileOperation.OperationStatus.Completed => FileOpFilter.FilterType.Completed,
14 | Services.FileOperation.OperationStatus.Canceled => FileOpFilter.FilterType.Canceled,
15 | Services.FileOperation.OperationStatus.Failed => FileOpFilter.FilterType.Failed,
16 | _ => throw new NotSupportedException(),
17 | };
18 |
19 | public string Name => AdbExplorerConst.FILE_OP_NAMES[FilterType];
20 |
21 | private bool isValidationInProgress = false;
22 | public bool IsValidationInProgress
23 | {
24 | get => isValidationInProgress;
25 | set => Set(ref isValidationInProgress, value);
26 | }
27 |
28 | public FileOpProgressViewModel(Services.FileOperation.OperationStatus status)
29 | {
30 | Status = status;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/FileOp/InProgShellProgressViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.ViewModels;
2 |
3 | internal class InProgShellProgressViewModel : FileOpProgressViewModel
4 | {
5 | public string CurrentFileName => null;
6 |
7 | public string CurrentFileNameWithoutExtension => null;
8 |
9 | public InProgShellProgressViewModel() : base(Services.FileOperation.OperationStatus.InProgress)
10 | {
11 |
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/FileOp/InProgSyncProgressViewModel.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.Converters;
2 | using ADB_Explorer.Services;
3 |
4 | namespace ADB_Explorer.ViewModels;
5 |
6 | internal class InProgSyncProgressViewModel : FileOpProgressViewModel
7 | {
8 | private readonly AdbSyncProgressInfo adbInfo = null;
9 |
10 | public InProgSyncProgressViewModel() : base(FileOperation.OperationStatus.InProgress)
11 | {
12 |
13 | }
14 |
15 | public InProgSyncProgressViewModel(AdbSyncProgressInfo adbInfo) : this()
16 | {
17 | this.adbInfo = adbInfo;
18 | }
19 |
20 | public int? TotalPercentage => adbInfo?.TotalPercentage;
21 |
22 | public ulong? TotalBytesTransferred => adbInfo?.TotalBytesTransferred;
23 |
24 | public string TotalBytes => TotalBytesTransferred?.ToSize();
25 |
26 | public int? CurrentFilePercentage => adbInfo?.CurrentFilePercentage;
27 |
28 | public UInt64? CurrentFileBytesTransferred => adbInfo?.CurrentFileBytesTransferred;
29 |
30 | public string CurrentFilePath => adbInfo?.AndroidPath;
31 |
32 | public string CurrentFileName => Path.GetFileName(CurrentFilePath);
33 |
34 | public string CurrentFileNameWithoutExtension => Path.GetFileNameWithoutExtension(CurrentFilePath);
35 | }
36 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/FileOp/WaitingOpProgressViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.ViewModels;
2 |
3 | internal class WaitingOpProgressViewModel : FileOpProgressViewModel
4 | {
5 | public WaitingOpProgressViewModel() : base(Services.FileOperation.OperationStatus.Waiting)
6 | {
7 |
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/ADB Explorer/ViewModels/ViewModelBase.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.ViewModels;
2 |
3 | public abstract class ViewModelBase : INotifyPropertyChanged
4 | {
5 | public event PropertyChangedEventHandler PropertyChanged;
6 |
7 | protected virtual bool Set(ref T storage, T value, [CallerMemberName] string propertyName = null)
8 | {
9 | if (Equals(storage, value))
10 | {
11 | return false;
12 | }
13 |
14 | storage = value;
15 | OnPropertyChanged(propertyName);
16 |
17 | return true;
18 | }
19 |
20 | protected void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
21 |
22 | public static void ExecuteInDispatcher(Action action)
23 | {
24 | // When running unit tests, App.Current is null
25 | if (App.Current is null)
26 | action();
27 | else
28 | App.Current.Dispatcher.Invoke(action);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Battery/CompactBatteryControl.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
22 |
23 |
28 |
29 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Battery/CompactBatteryControl.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Views;
2 |
3 | ///
4 | /// Interaction logic for CompactBatteryControl.xaml
5 | ///
6 | public partial class CompactBatteryControl : UserControl
7 | {
8 | public CompactBatteryControl()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Battery/DetailedBatteryControl.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Views;
2 |
3 | ///
4 | /// Interaction logic for DetailedBatteryControl.xaml
5 | ///
6 | public partial class DetailedBatteryControl : UserControl
7 | {
8 | public DetailedBatteryControl()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Device/HistoryDeviceControl.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Views;
2 |
3 | ///
4 | /// Interaction logic for HistoryDeviceControl.xaml
5 | ///
6 | public partial class HistoryDeviceControl : UserControl
7 | {
8 | public HistoryDeviceControl()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Device/LogicalDeviceControl.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Views;
2 |
3 | ///
4 | /// Interaction logic for LogicalDeviceControl.xaml
5 | ///
6 | public partial class LogicalDeviceControl : UserControl
7 | {
8 | public LogicalDeviceControl()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Device/NewDeviceControl.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Views;
2 |
3 | ///
4 | /// Interaction logic for NewDeviceControl.xaml
5 | ///
6 | public partial class NewDeviceControl : UserControl
7 | {
8 | public NewDeviceControl()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Device/ServiceDeviceControl.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
56 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Device/ServiceDeviceControl.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Views;
2 |
3 | ///
4 | /// Interaction logic for ServiceDeviceControl.xaml
5 | ///
6 | public partial class ServiceDeviceControl : UserControl
7 | {
8 | public ServiceDeviceControl()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Device/WsaPkgDeviceControl.xaml:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
48 |
49 |
50 |
51 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Device/WsaPkgDeviceControl.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace ADB_Explorer.Views
2 | {
3 | ///
4 | /// Interaction logic for WsaPkgDeviceControl.xaml
5 | ///
6 | public partial class WsaPkgDeviceControl : UserControl
7 | {
8 | public WsaPkgDeviceControl()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Drive/LogicalDriveControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.ViewModels;
2 |
3 | namespace ADB_Explorer.Views;
4 |
5 | ///
6 | /// Interaction logic for LogicalDriveControl.xaml
7 | ///
8 | public partial class LogicalDriveControl : UserControl
9 | {
10 | public LogicalDriveControl()
11 | {
12 | InitializeComponent();
13 | }
14 |
15 | private void Button_MouseDoubleClick(object sender, MouseButtonEventArgs e)
16 | {
17 | if (((Button)sender).DataContext is DriveViewModel drive)
18 | drive.BrowseCommand.Execute();
19 | }
20 |
21 | private void Button_PreviewMouseUp(object sender, MouseButtonEventArgs e)
22 | {
23 | if (((Button)sender).DataContext is DriveViewModel drive)
24 | drive.SelectCommand.Execute();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ADB Explorer/Views/Drive/VirtualDriveControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using ADB_Explorer.ViewModels;
2 |
3 | namespace ADB_Explorer.Views;
4 |
5 | ///
6 | /// Interaction logic for VirtualDriveControl.xaml
7 | ///
8 | public partial class VirtualDriveControl : UserControl
9 | {
10 | public VirtualDriveControl()
11 | {
12 | InitializeComponent();
13 | }
14 |
15 | private void Button_MouseDoubleClick(object sender, MouseButtonEventArgs e)
16 | {
17 | ((DriveViewModel)((Button)sender).DataContext).BrowseCommand.Execute();
18 | }
19 |
20 | private void Button_PreviewMouseUp(object sender, MouseButtonEventArgs e)
21 | {
22 | ((DriveViewModel)((Button)sender).DataContext).SelectCommand.Execute();
23 | }
24 |
25 | private void Button_KeyUp(object sender, KeyEventArgs e)
26 | {
27 | if (e.Key is Key.Enter)
28 | {
29 | ((DriveViewModel)((Button)sender).DataContext).BrowseCommand.Execute();
30 | e.Handled = true;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ADB Explorer/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | true/PM
7 | PerMonitorV2, PerMonitor
8 | true
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/ADB Explorer/app_icon_2023_combined.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Explorer/app_icon_2023_combined.ico
--------------------------------------------------------------------------------
/ADB Explorer/app_icon_black_2023_256px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Explorer/app_icon_black_2023_256px.png
--------------------------------------------------------------------------------
/ADB Package/Images/LargeTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/LargeTile.scale-100.png
--------------------------------------------------------------------------------
/ADB Package/Images/LargeTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/LargeTile.scale-125.png
--------------------------------------------------------------------------------
/ADB Package/Images/LargeTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/LargeTile.scale-150.png
--------------------------------------------------------------------------------
/ADB Package/Images/LargeTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/LargeTile.scale-200.png
--------------------------------------------------------------------------------
/ADB Package/Images/LargeTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/LargeTile.scale-400.png
--------------------------------------------------------------------------------
/ADB Package/Images/SmallTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/SmallTile.scale-100.png
--------------------------------------------------------------------------------
/ADB Package/Images/SmallTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/SmallTile.scale-125.png
--------------------------------------------------------------------------------
/ADB Package/Images/SmallTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/SmallTile.scale-150.png
--------------------------------------------------------------------------------
/ADB Package/Images/SmallTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/SmallTile.scale-200.png
--------------------------------------------------------------------------------
/ADB Package/Images/SmallTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/SmallTile.scale-400.png
--------------------------------------------------------------------------------
/ADB Package/Images/SplashScreen.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/SplashScreen.scale-100.png
--------------------------------------------------------------------------------
/ADB Package/Images/SplashScreen.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/SplashScreen.scale-125.png
--------------------------------------------------------------------------------
/ADB Package/Images/SplashScreen.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/SplashScreen.scale-150.png
--------------------------------------------------------------------------------
/ADB Package/Images/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/ADB Package/Images/SplashScreen.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/SplashScreen.scale-400.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square150x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square150x150Logo.scale-100.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square150x150Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square150x150Logo.scale-125.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square150x150Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square150x150Logo.scale-150.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square150x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square150x150Logo.scale-400.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.altform-lightunplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.altform-lightunplated_targetsize-16.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.altform-lightunplated_targetsize-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.altform-lightunplated_targetsize-24.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.altform-lightunplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.altform-lightunplated_targetsize-256.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.altform-lightunplated_targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.altform-lightunplated_targetsize-32.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.altform-lightunplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.altform-lightunplated_targetsize-48.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.altform-unplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.altform-unplated_targetsize-16.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.altform-unplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.altform-unplated_targetsize-256.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.altform-unplated_targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.altform-unplated_targetsize-32.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.altform-unplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.altform-unplated_targetsize-48.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.scale-100.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.scale-125.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.scale-150.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.scale-400.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.targetsize-16.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.targetsize-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.targetsize-24.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.targetsize-256.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.targetsize-32.png
--------------------------------------------------------------------------------
/ADB Package/Images/Square44x44Logo.targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Square44x44Logo.targetsize-48.png
--------------------------------------------------------------------------------
/ADB Package/Images/StoreLogo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/StoreLogo.scale-100.png
--------------------------------------------------------------------------------
/ADB Package/Images/StoreLogo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/StoreLogo.scale-125.png
--------------------------------------------------------------------------------
/ADB Package/Images/StoreLogo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/StoreLogo.scale-150.png
--------------------------------------------------------------------------------
/ADB Package/Images/StoreLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/StoreLogo.scale-200.png
--------------------------------------------------------------------------------
/ADB Package/Images/StoreLogo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/StoreLogo.scale-400.png
--------------------------------------------------------------------------------
/ADB Package/Images/Wide310x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Wide310x150Logo.scale-100.png
--------------------------------------------------------------------------------
/ADB Package/Images/Wide310x150Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Wide310x150Logo.scale-125.png
--------------------------------------------------------------------------------
/ADB Package/Images/Wide310x150Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Wide310x150Logo.scale-150.png
--------------------------------------------------------------------------------
/ADB Package/Images/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/ADB Package/Images/Wide310x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/ADB Package/Images/Wide310x150Logo.scale-400.png
--------------------------------------------------------------------------------
/ADB Package/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 | ADB Explorer
16 | AlexSSB
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 |
--------------------------------------------------------------------------------
/ADB Package/Strings/en-us/Resources.resw:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | text/microsoft-resx
32 |
33 |
34 | 1.3
35 |
36 |
37 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
38 |
39 |
40 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
41 |
42 |
43 | ADB Explorer
44 | Application display name
45 |
46 |
47 | ADB Explorer
48 | Application description
49 |
50 |
--------------------------------------------------------------------------------
/ADB_Test/ADB_Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0-windows10.0.22621.0
5 |
6 | false
7 |
8 | AnyCPU;x64
9 |
10 | 10.0.18362.0
11 |
12 | Debug;Release;Deploy
13 |
14 |
15 |
16 | x64
17 |
18 |
19 |
20 | x64
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | all
29 | runtime; build; native; contentfiles; analyzers; buildtransitive
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/AdbProgressRedirection/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.associations": {
3 | "algorithm": "cpp",
4 | "atomic": "cpp",
5 | "bit": "cpp",
6 | "cctype": "cpp",
7 | "charconv": "cpp",
8 | "clocale": "cpp",
9 | "cmath": "cpp",
10 | "compare": "cpp",
11 | "concepts": "cpp",
12 | "cstddef": "cpp",
13 | "cstdint": "cpp",
14 | "cstdio": "cpp",
15 | "cstdlib": "cpp",
16 | "cstring": "cpp",
17 | "ctime": "cpp",
18 | "cwchar": "cpp",
19 | "exception": "cpp",
20 | "format": "cpp",
21 | "initializer_list": "cpp",
22 | "ios": "cpp",
23 | "iosfwd": "cpp",
24 | "iostream": "cpp",
25 | "istream": "cpp",
26 | "iterator": "cpp",
27 | "limits": "cpp",
28 | "locale": "cpp",
29 | "memory": "cpp",
30 | "new": "cpp",
31 | "numeric": "cpp",
32 | "optional": "cpp",
33 | "ostream": "cpp",
34 | "stdexcept": "cpp",
35 | "streambuf": "cpp",
36 | "string": "cpp",
37 | "system_error": "cpp",
38 | "tuple": "cpp",
39 | "type_traits": "cpp",
40 | "typeinfo": "cpp",
41 | "utility": "cpp",
42 | "vector": "cpp",
43 | "xfacet": "cpp",
44 | "xiosbase": "cpp",
45 | "xlocale": "cpp",
46 | "xlocbuf": "cpp",
47 | "xlocinfo": "cpp",
48 | "xlocmes": "cpp",
49 | "xlocmon": "cpp",
50 | "xlocnum": "cpp",
51 | "xloctime": "cpp",
52 | "xmemory": "cpp",
53 | "xstring": "cpp",
54 | "xtr1common": "cpp",
55 | "xutility": "cpp"
56 | }
57 | }
--------------------------------------------------------------------------------
/AdbProgressRedirection/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "label": "Build",
8 | "type": "shell",
9 | "command": "g++ -std=c++17 -O3 -Wall -pedantic -o output/AdbProgressRedirection.exe main.cpp -municode -static",
10 | "problemMatcher": [
11 | "$gcc"
12 | ],
13 | "group": {
14 | "kind": "build",
15 | "isDefault": true
16 | }
17 | },
18 | {
19 | "label": "Clean",
20 | "type": "shell",
21 | "command": "rm output/AdbProgressRedirection.exe",
22 | "problemMatcher": []
23 | }
24 | ]
25 | }
--------------------------------------------------------------------------------
/AdbProgressRedirection/AdbProgressRedirection.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
--------------------------------------------------------------------------------
/AdbProgressRedirection/output/.placeholder:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/AdbProgressRedirection/output/.placeholder
--------------------------------------------------------------------------------
/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: alex4ssb
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Alex B
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Privacy.md:
--------------------------------------------------------------------------------
1 | # Privacy Policy
2 |
3 | No information is being sent on our behalf over the web, and we do not collect any personal data. For information about data collected by Microsoft Store please see its terms.
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
ADB Explorer
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | An interface to ADB that allows browsing, transferring, and editing of files with ease, in a modern and fluent Windows app, built in WPF.
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Translation
30 | Help with translation is most welcome - please visit our translation project on Weblate: https://hosted.weblate.org/engage/adb-explorer/
31 |
32 | A Microsoft Store review:
33 |
34 | > 超级赞!!!传输文件快、稳的一匹!!!找个方法替换一下支持中文!!!
35 |
36 |
37 | App Files
38 |
39 | `%LocalAppData%\AdbExplorer`
40 |
41 |
42 | ### ℹ️ For Store version: To be able to see these files, create `%LocalAppData%\AdbExplorer\App.txt` *before installing*, otherwise the files are stored in an unknown location.
43 |
44 |
45 | * App.txt - persistent settings file.
46 | * AdbProgressRedirection.exe - a pipe for getting progress updates while executing ADB push & pull commands.
47 | * TEMP - a folder to which edited files are transferred temporarily.
48 | * TempDrag... - folder(s) to which files are temporarily transferred for Drag & Drop / Clipboard transfer to PC.
49 |
50 | The settings file contains user app settings as well as other settings not directly accessible.
51 | The file can be edited, but the format must be preserved.
52 | An unrecognized entry will be overwritten.
53 | The file can be deleted to restore app settings to their defaults.
54 |
55 | Compiling AdbProgressRedirection for x64
56 | To minimize false positive AV detection of AdbProgressRedirection.exe, the x64 build is not done in Visual Studio, but using a specific version of UCRT.
57 | This leaves us with only Bkav Pro detection which is (aparently) infamous for its false positives.
58 |
59 |
60 | 1. [Download GCC 13.3 with UCRT64](https://github.com/brechtsanders/winlibs_mingw/releases/tag/13.3.0posix-11.0.1-ucrt-r1)
61 | 2. Extract somewhere
62 | 3. Add to environment Path `[extracted path]\mingw64\bin`
63 | 4. Open the AdbProgressRedirection folder in VS Code
64 | 5. Build (Ctrl+Shift+B)
65 |
--------------------------------------------------------------------------------
/ResXCleaner/ResxCleaner.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | ResX_Cleaner
7 | enable
8 | enable
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/icons/APK_format_icon_(2014-2019).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/APK_format_icon_(2014-2019).png
--------------------------------------------------------------------------------
/icons/APK_format_icon_2014-2019_.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/APK_format_icon_2014-2019_.ico
--------------------------------------------------------------------------------
/icons/App_icon.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/App_icon.pdn
--------------------------------------------------------------------------------
/icons/Store_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/Store_icon.png
--------------------------------------------------------------------------------
/icons/Store_icon_2023.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/Store_icon_2023.png
--------------------------------------------------------------------------------
/icons/Store_icon_beta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/Store_icon_beta.png
--------------------------------------------------------------------------------
/icons/Store_icon_beta_2023.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/Store_icon_beta_2023.png
--------------------------------------------------------------------------------
/icons/Store_icon_v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/Store_icon_v2.png
--------------------------------------------------------------------------------
/icons/Store_icon_v3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/Store_icon_v3.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v2_icons8.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v2_icons8.ico
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v2_icons8.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v2_icons8.pdn
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v2_icons8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v2_icons8.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v3_icons8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v3_icons8.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v3_icons8_tile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v3_icons8_tile.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8.ico
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8_combined.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8_combined.ico
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8_inverted - Copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8_inverted - Copy.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8_inverted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8_inverted.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8_medium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8_medium.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8_medium_v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8_medium_v2.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8_medium_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8_medium_white.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8_simple _white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8_simple _white.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8_simple.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8_simple.ico
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8_simple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8_simple.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8_simple_v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8_simple_v2.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v4_icons8_tile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v4_icons8_tile.png
--------------------------------------------------------------------------------
/icons/adb_explorer_icon_v5_icons8_combined.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/adb_explorer_icon_v5_icons8_combined.ico
--------------------------------------------------------------------------------
/icons/app_icon_black_2023.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/app_icon_black_2023.png
--------------------------------------------------------------------------------
/icons/app_icon_black_2023_256px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/app_icon_black_2023_256px.png
--------------------------------------------------------------------------------
/icons/app_icon_white_2023.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/app_icon_white_2023.png
--------------------------------------------------------------------------------
/icons/icons8-android-os-240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/icons8-android-os-240.png
--------------------------------------------------------------------------------
/icons/icons8-android-os-250.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/icons8-android-os-250.png
--------------------------------------------------------------------------------
/icons/icons8-folder-208.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/icons8-folder-208.png
--------------------------------------------------------------------------------
/icons/icons8-folder-250.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/icons8-folder-250.png
--------------------------------------------------------------------------------
/icons/icons8-sync-100 - Copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/icons8-sync-100 - Copy.png
--------------------------------------------------------------------------------
/icons/icons8-sync-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/icons8-sync-100.png
--------------------------------------------------------------------------------
/icons/icons8_folder&sync&android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/icons8_folder&sync&android.png
--------------------------------------------------------------------------------
/icons/icons8_folder&sync.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alex4SSB/ADB-Explorer/84077b57171e9333a6744712f69eeb683cbede15/icons/icons8_folder&sync.png
--------------------------------------------------------------------------------
/licences/Android_icon_license.txt:
--------------------------------------------------------------------------------
1 | The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License.
--------------------------------------------------------------------------------
/licences/Apache License.txt:
--------------------------------------------------------------------------------
1 | https://www.apache.org/licenses/LICENSE-2.0
--------------------------------------------------------------------------------
/licences/CC BY-SA 3.0.txt:
--------------------------------------------------------------------------------
1 | https://creativecommons.org/licenses/by-sa/3.0/
--------------------------------------------------------------------------------
/licences/icons8.com license.txt:
--------------------------------------------------------------------------------
1 | macOS and Windows applications should have the link to https://icons8.com in the about section.
--------------------------------------------------------------------------------