diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Elements/Native/FolderPicker.cs b/src/BfmeFoundationProject_AllInOneLauncher/Elements/Native/FolderPicker.cs
new file mode 100644
index 0000000..adfce4f
--- /dev/null
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Elements/Native/FolderPicker.cs
@@ -0,0 +1,33 @@
+using System;
+using System.IO;
+using System.Windows;
+using Microsoft.Win32;
+
+namespace BfmeFoundationProject.AllInOneLauncher.Elements.Native;
+
+internal static class FolderPicker
+{
+ public static string? ShowDialog(Window owner, string title = "", string? initialPath = null)
+ {
+ var dlg = new OpenFolderDialog
+ {
+ Title = title,
+ ValidateNames = true,
+ };
+
+ if (Directory.Exists(initialPath))
+ {
+ dlg.InitialDirectory = initialPath;
+ }
+
+ bool? result = dlg.ShowDialog(owner);
+ if (result == true)
+ {
+ var selected = dlg.FolderName;
+ if (Directory.Exists(selected))
+ return selected;
+ }
+
+ return null;
+ }
+}
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Pages/Primary/Offline.xaml.cs b/src/BfmeFoundationProject_AllInOneLauncher/Pages/Primary/Offline.xaml.cs
index e16a98e..5bad012 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Pages/Primary/Offline.xaml.cs
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Pages/Primary/Offline.xaml.cs
@@ -113,8 +113,15 @@ private void OnLaunchGameClicked(object sender, EventArgs e)
private void OnInstallGameClicked(object sender, EventArgs e)
{
- PopupVisualizer.ShowPopup(new InstallGamePopup(),
- OnPopupSubmited: async (submittedData) => await BfmeSyncManager.InstallGame((BfmeGame)gameTabs.SelectedIndex, submittedData[0], submittedData[1]));
+ try
+ {
+ PopupVisualizer.ShowPopup(new InstallGamePopup(),
+ OnPopupSubmited: async (submittedData) => await BfmeSyncManager.InstallGame((BfmeGame)gameTabs.SelectedIndex, submittedData[0], submittedData[1]));
+ }
+ catch (Exception ex)
+ {
+ PopupVisualizer.ShowPopup(new ErrorPopup(ex));
+ }
}
private async void TabChanged(object sender, EventArgs e)
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Popups/InstallGamePopup.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Popups/InstallGamePopup.xaml
index 31ce196..634332c 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Popups/InstallGamePopup.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Popups/InstallGamePopup.xaml
@@ -9,6 +9,7 @@
xmlns:generic="clr-namespace:BfmeFoundationProject.AllInOneLauncher.Elements.Generic"
mc:Ignorable="d"
Width="700" HorizontalAlignment="Center" VerticalAlignment="Center">
+
@@ -17,7 +18,7 @@
-
+
@@ -48,7 +49,7 @@
-
+
English
French
@@ -62,14 +63,42 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Popups/InstallGamePopup.xaml.cs b/src/BfmeFoundationProject_AllInOneLauncher/Popups/InstallGamePopup.xaml.cs
index 38815dd..a00c3f3 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Popups/InstallGamePopup.xaml.cs
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Popups/InstallGamePopup.xaml.cs
@@ -1,48 +1,113 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
+using System.IO;
using System.Windows;
+using BfmeFoundationProject.AllInOneLauncher.Core.Utils;
using BfmeFoundationProject.AllInOneLauncher.Elements.Disk;
using BfmeFoundationProject.AllInOneLauncher.Elements.Generic;
+using BfmeFoundationProject.AllInOneLauncher.Elements.Native;
namespace BfmeFoundationProject.AllInOneLauncher.Popups;
public partial class InstallGamePopup : PopupBody
{
- private static readonly Dictionary Drives = DriveInfo.GetDrives().ToDictionary(x => x.RootDirectory.FullName);
+ private readonly List Drives = DriveUtils.GetValidDrives();
+ private readonly string DefaultPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
public InstallGamePopup()
{
InitializeComponent();
- locations.Children.Clear();
- foreach (var drive in Drives.Values)
+ if (Drives.Count <= 0)
{
- if (!drive.IsReady)
- continue;
-
- try
+ SelectLocationError.Visibility = Visibility.Visible;
+ SelectLocationArea.Visibility = Visibility.Collapsed;
+ }
+ else
+ {
+ SelectLocationSelectableList.Children.Clear();
+ Drives.ForEach(drive =>
{
- locations.Children.Add(new Selectable()
+ SelectLocationSelectableList.Children.Add(new Selectable()
{
Title = new LibraryDriveHeader()
{
LibraryDriveName = string.Concat(drive.VolumeLabel, " (", drive.Name.Replace(@"\", ""), ")"),
- LibraryDriveSize = $"{Math.Floor(drive.AvailableFreeSpace / Math.Pow(1024, 3)):N0} GB {App.Current.FindResource("GenericFree")}",
+ LibraryDriveSize = GetDriveFreeSpaceFormatted(drive),
Mini = true
},
- Tag = drive.RootDirectory.FullName,
+ Tag = DriveUtils.GetDriveRootName(drive),
Margin = new Thickness(0, 0, 0, 5),
UseLayoutRounding = true,
SnapsToDevicePixels = true
});
+
+ });
+
+ SetSelectedPath(DefaultPath);
+ }
+ }
+
+ private void SetSelectedPath(string path)
+ {
+ string? selectedPath = null;
+ var selectedFreeText = string.Empty;
+ try
+ {
+ selectedPath = DriveUtils.GetValidPath(path);
+ var drive = DriveUtils.GetDriveForPath(Drives, selectedPath);
+ if (drive == null)
+ {
+ selectedPath = DriveUtils.GetValidPath(DefaultPath);
+ drive = DriveUtils.GetDriveForPath(Drives, selectedPath);
}
- catch { }
+
+ if (drive != null)
+ {
+ selectedFreeText = GetDriveFreeSpaceFormatted(drive);
+ }
+ }
+ catch { /* ignore errors here */ }
+
+ SelectedPathText.Text = selectedPath;
+ SelectedFreeSpaceText.Text = selectedFreeText;
+ ButtonAccept.IsEnabled = !string.IsNullOrWhiteSpace(selectedPath);
+ }
+
+ private static string GetDriveFreeSpaceFormatted(DriveInfo drive)
+ {
+ return $"{Math.Floor(drive.AvailableFreeSpace / Math.Pow(1024, 3)):N0} GB {App.Current.FindResource("GenericFree")}";
+ }
+
+ private void OnSelectFolderClicked(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ var ownerWindow = Window.GetWindow(this);
+ var folderDialogTitle = (string)App.Current.FindResource("InstallGamePopupSelectFolder");
+ var selectedPath = SelectedPathText.Text;
+ var selected = FolderPicker.ShowDialog(ownerWindow, folderDialogTitle, selectedPath);
+ if (!string.IsNullOrWhiteSpace(selected))
+ SetSelectedPath(selected);
+ }
+ catch (Exception ex)
+ {
+ PopupVisualizer.ShowPopup(new ErrorPopup(ex));
+ Dismiss();
}
}
- private void OnInstallClicked(object sender, RoutedEventArgs e) => Submit(LanguageDropdown.SelectedValue, Selectable.GetSelectedTagInContainer(locations)!.ToString()!);
+ private void OnAdvancedSettingsSwitched(object sender, EventArgs e)
+ {
+ var isActive = SelectLocationAdvancedToggle.IsToggled;
+ SelectLocationSelectableList.Visibility = isActive ? Visibility.Hidden : Visibility.Visible;
+ SelectLocationAdvancedArea.Visibility = isActive ? Visibility.Visible : Visibility.Hidden;
+ }
+
+ private void OnInstallClicked(object sender, RoutedEventArgs e)
+ {
+ var language = LanguageDropdown.SelectedValue;
+ var path = (SelectLocationAdvancedToggle.IsToggled == true) ? SelectedPathText.Text : Selectable.GetSelectedTagInContainer(SelectLocationSelectableList)!.ToString()!;
+ Submit(language, path);
+ }
private void OnCancelClicked(object sender, RoutedEventArgs e) => Dismiss();
}
\ No newline at end of file
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.ar.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.ar.xaml
index b83cc5b..d91ea84 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.ar.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.ar.xaml
@@ -107,6 +107,9 @@
تثبيت اللعبة
اللغة
الموقع
+ متقدم
+ اختر مجلد التثبيت
+ لا توجد أقراص متاحة
إضافة إلى المكتبة
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.de.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.de.xaml
index 2ab564d..33680fa 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.de.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.de.xaml
@@ -20,8 +20,6 @@
JA
NEIN
-
-
EINZELSPIELER
Mehrspieler
@@ -119,6 +117,9 @@
SPIEL INSTALLIEREN
Sprache
Standort
+ Fortgeschritten
+ Installationsordner wählen
+ Keine Laufwerke verfügbar
ZUR BIBLIOTHEK HINZUFÜGEN
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.en.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.en.xaml
index 4af525c..f5f9458 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.en.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.en.xaml
@@ -20,8 +20,6 @@
YES
NO
-
-
SINGLEPLAYER
MULTIPLAYER
@@ -121,6 +119,9 @@
INSTALL GAME
Language
Location
+ Advanced
+ Select installation folder
+ No drives available
ADD TO LIBRARY
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.es.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.es.xaml
index 5ffe176..80ad24c 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.es.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.es.xaml
@@ -107,6 +107,9 @@
INSTALAR JUEGO
Idioma
Ubicación
+ Avanzado
+ Seleccionar carpeta de instalación
+ No hay unidades disponibles
AÑADIR A LA BIBLIOTECA
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.fr.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.fr.xaml
index 91e8193..0306ecf 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.fr.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.fr.xaml
@@ -107,6 +107,9 @@
INSTALLER LE JEU
Langue
Emplacement
+ Avancé
+ Sélectionner le dossier d'installation
+ Aucun disque disponible
AJOUTER À LA BIBLIOTHÈQUE
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.hu.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.hu.xaml
index 3b22fb9..76fd584 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.hu.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.hu.xaml
@@ -17,6 +17,7 @@
IGEN
IGEN
NEM
+ FIGYELMEZTETÉS
EGYJÁTÉKOS
@@ -107,6 +108,9 @@
JÁTÉK TELEPÍTÉSE
Nyelv
Helyszín
+ Haladó
+ Válassza ki a telepítési mappát
+ Nincsenek elérhető meghajtók
KÖNYVTÁRBAN HOZZÁADÁS
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.it.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.it.xaml
index 46b8eaf..ff9a199 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.it.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.it.xaml
@@ -107,6 +107,9 @@
INSTALLA GIOCO
Lingua
Posizione
+ Avanzato
+ Seleziona la cartella di installazione
+ Nessun disco disponibile
AGGIUNGI ALLA BIBLIOTECA
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.nl.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.nl.xaml
index 960e47e..e397551 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.nl.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.nl.xaml
@@ -107,6 +107,9 @@
GAME INSTALLEREN
Taal
Locatie
+ Geavanceerd
+ Selecteer installatiemap
+ Geen stations beschikbaar
TOEVOEGEN AAN BIBLIOTHEEK
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.no.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.no.xaml
index 65a5a5b..582ce87 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.no.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.no.xaml
@@ -107,6 +107,9 @@
INSTALLER SPILL
Språk
Beliggenhet
+ Avansert
+ Velg installasjonsmappe
+ Ingen stasjoner tilgjengelig
LEGG TIL I BIBLIOTEKET
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.pl.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.pl.xaml
index eda66b0..5274176 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.pl.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.pl.xaml
@@ -107,6 +107,9 @@
INSTALUJ GRĘ
Język
Lokalizacja
+ Zaawansowane
+ Wybierz folder instalacyjny
+ Brak dostępnych dysków
DODAJ DO BIBLIOTEKI
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.ru.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.ru.xaml
index 9733594..47d7b4a 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.ru.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.ru.xaml
@@ -107,6 +107,9 @@
УСТАНОВКА ИГРЫ
Язык
Местоположение
+ Дополнительно
+ Выберите папку для установки
+ Дисков не найдено
ДОБАВИТЬ В БИБЛИОТЕКУ
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.sv.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.sv.xaml
index 16ecd23..24d1f3c 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.sv.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.sv.xaml
@@ -107,6 +107,9 @@
INSTALLERA SPEL
Språk
Plats
+ Avancerat
+ Välj installationsmapp
+ Inga enheter tillgängliga
LÄGG TILL I BIBLIOTEKET
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.tr.xaml b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.tr.xaml
index 76a3df6..fb82d6d 100644
--- a/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.tr.xaml
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Resources/Dictionary/LanguageResources.tr.xaml
@@ -20,8 +20,6 @@
EVET
HAYIR
-
-
TEK OYUNCU
ÇOK OYUNCULU
@@ -121,6 +119,9 @@
OYUNU YÜKLE
Dil
Konum
+ Gelişmiş
+ Yükleme klasörünü seçin
+ Hiçbir sürücü bulunamadı
KÜTÜPHANEYE EKLE
diff --git a/src/BfmeFoundationProject_AllInOneLauncher/Utils/DriveUtils.cs b/src/BfmeFoundationProject_AllInOneLauncher/Utils/DriveUtils.cs
new file mode 100644
index 0000000..7aa5a07
--- /dev/null
+++ b/src/BfmeFoundationProject_AllInOneLauncher/Utils/DriveUtils.cs
@@ -0,0 +1,50 @@
+using System;
+using System.IO;
+
+namespace BfmeFoundationProject.AllInOneLauncher.Core.Utils;
+
+public class DriveUtils
+{
+ /**
+ Only Local Disk drives that are ready are valid.
+ No Network or removable drives.
+ */
+ public static bool IsValidDrive(DriveInfo drive)
+ {
+ return drive.DriveType == DriveType.Fixed && drive.IsReady;
+ }
+
+ public static List GetValidDrives()
+ {
+ return DriveInfo.GetDrives().Where(d => IsValidDrive(d)).ToList();
+ }
+
+ public static DriveInfo? GetDriveForPath(List somedrives, string? path)
+ {
+ DriveInfo? drive = null;
+
+ var driveRoot = Path.GetPathRoot(path);
+ if (!string.IsNullOrWhiteSpace(driveRoot))
+ {
+ drive = somedrives.FirstOrDefault(d => GetDriveRootName(d).Equals(driveRoot, StringComparison.OrdinalIgnoreCase));
+ }
+
+ return drive;
+ }
+
+ public static string GetDriveRootName(DriveInfo drive)
+ {
+ return drive.RootDirectory.FullName;
+ }
+
+ internal static string? GetValidPath(string path)
+ {
+ string? fullpath = null;
+ if(Directory.Exists(path)) {
+ fullpath = Path.GetFullPath(path);
+ }
+
+ var noExcludedFolders = fullpath != null && !fullpath.Contains(":\\Windows") && !fullpath.Contains("\\OneDrive");
+ return noExcludedFolders ? fullpath : null;
+ }
+}