1
0
Fork 0
mirror of https://github.com/hawkeye-stan/msfs-popout-panel-manager.git synced 2024-12-28 07:11:59 +00:00

Version 4.1.1 Release

This commit is contained in:
hawkeye 2024-07-27 20:12:07 -04:00
parent b9d21d58ee
commit 8f82f9a785
29 changed files with 321 additions and 229 deletions

View file

@ -144,7 +144,7 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
private static string GetFilePath() private static string GetFilePath()
{ {
var filePathMsStore = Environment.ExpandEnvironmentVariables("%LocalAppData%") + @"\Packages\Microsoft.FlightSimulator_8wekyb3d8bbwe\LocalCache\"; var filePathMsStore = Environment.ExpandEnvironmentVariables("%LocalAppData%") + @"\Packages\Microsoft.FlightSimulator_8wekyb3d8bbwe\LocalCache\";
var filePathSteam = Environment.ExpandEnvironmentVariables("%AppData%") + @"\Microsoft Flight Simulator\LocalCache\"; var filePathSteam = Environment.ExpandEnvironmentVariables("%AppData%") + @"\Microsoft Flight Simulator\";
if (Directory.Exists(filePathMsStore)) if (Directory.Exists(filePathMsStore))
return filePathMsStore + "exe.xml"; return filePathMsStore + "exe.xml";
@ -187,5 +187,8 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
[XmlElement(ElementName = "Path")] [XmlElement(ElementName = "Path")]
public string Path { get; set; } public string Path { get; set; }
[XmlElement(ElementName = "CommandLine")]
public string CommandLine { get; set; }
} }
} }

View file

@ -23,7 +23,7 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
public int TargetedFps { get; set; } = 60; public int TargetedFps { get; set; } = 60;
public int FpsTolerance { get; set; } = 5; public int FpsTolerance { get; set; } = 4;
public bool TlodMinOnGround { get; set; } = true; public bool TlodMinOnGround { get; set; } = true;
@ -31,13 +31,13 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
public int TlodMin { get; set; } = 50; public int TlodMin { get; set; } = 50;
public int TlodMax { get; set; } = 400; public int TlodMax { get; set; } = 200;
public int CloudRecoveryTlod { get; set; } = 100; public int CloudRecoveryTlod { get; set; } = 100;
public bool DecreaseCloudQuality { get; set; } = true; public bool DecreaseCloudQuality { get; set; } = false;
public int OlodTop { get; set; } = 20; public int OlodTop { get; set; } = 50;
public int OlodBase { get; set; } = 200; public int OlodBase { get; set; } = 200;

View file

@ -1,4 +1,5 @@
using MSFSPopoutPanelManager.Shared; using System;
using MSFSPopoutPanelManager.Shared;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace MSFSPopoutPanelManager.DomainModel.Setting namespace MSFSPopoutPanelManager.DomainModel.Setting
@ -8,6 +9,17 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
public GeneralSetting() public GeneralSetting()
{ {
InitializeChildPropertyChangeBinding(); InitializeChildPropertyChangeBinding();
PropertyChanged += (_, e) =>
{
if (e.PropertyName == "UseApplicationDataPath")
{
OnApplicationDataPathUpdated?.Invoke(this, UseApplicationDataPath);
ApplicationDataPath = FileIo.GetUserDataFilePath(UseApplicationDataPath);
}
};
ApplicationDataPath = FileIo.GetUserDataFilePath(UseApplicationDataPath);
} }
public bool AlwaysOnTop { get; set; } = true; public bool AlwaysOnTop { get; set; } = true;
@ -22,6 +34,8 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
public bool TurboMode { get; set; } = false; public bool TurboMode { get; set; } = false;
public bool UseApplicationDataPath { get; set; } = false;
[JsonIgnore, IgnorePropertyChanged] [JsonIgnore, IgnorePropertyChanged]
public bool AutoStart public bool AutoStart
{ {
@ -34,5 +48,10 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
AppAutoStart.Deactivate(); AppAutoStart.Deactivate();
} }
} }
[JsonIgnore]
public string ApplicationDataPath { get; set; }
public event EventHandler<bool> OnApplicationDataPathUpdated;
} }
} }

View file

@ -43,7 +43,9 @@ namespace MSFSPopoutPanelManager.MainApp
// Setup all data storage objects // Setup all data storage objects
SharedStorage = new SharedStorage(); SharedStorage = new SharedStorage();
SharedStorage.AppSettingData.ReadSettings(); SharedStorage.AppSettingData.ReadSettings();
SharedStorage.ProfileData.AppSettingDataRef = SharedStorage.AppSettingData;
SharedStorage.ProfileData.ReadProfiles(); SharedStorage.ProfileData.ReadProfiles();
FileLogger.UseApplicationDataPath = SharedStorage.AppSettingData.ApplicationSetting.GeneralSetting.UseApplicationDataPath;
// Setup dependency injections // Setup dependency injections
AppHost = Host.CreateDefaultBuilder() AppHost = Host.CreateDefaultBuilder()

View file

@ -247,14 +247,6 @@
Stroke="Gray" Stroke="Gray"
X2="1" /> X2="1" />
</WrapPanel> </WrapPanel>
<TextBlock Width="Auto" Margin="0,0,0,0">
<Hyperlink
NavigateUri="Open Data Folder"
RequestNavigate="Hyperlink_RequestNavigate"
Style="{StaticResource MaterialDesignBody2Hyperlink}">
<TextBlock Text="Open application data file folder" />
</Hyperlink>
</TextBlock>
<TextBlock Width="Auto" Margin="0,10,0,0"> <TextBlock Width="Auto" Margin="0,10,0,0">
<Hyperlink <Hyperlink
NavigateUri="Download VCC Library" NavigateUri="Download VCC Library"
@ -273,16 +265,6 @@
KeyboardNavigation.AcceptsReturn="False" KeyboardNavigation.AcceptsReturn="False"
Style="{StaticResource MaterialDesignOutlinedButton}" Style="{StaticResource MaterialDesignOutlinedButton}"
ToolTip="This will delete all orphan application cache files in your Windows user account 'AppData/Local/Temp/.net/MSFSPopoutPanelManager' folder" /> ToolTip="This will delete all orphan application cache files in your Windows user account 'AppData/Local/Temp/.net/MSFSPopoutPanelManager' folder" />
<!--<Button
Width="280"
Margin="0,10,0,0"
HorizontalAlignment="Left"
Command="{Binding RollBackCommand}"
Content="Rollback to previous version 3.4.6.0321"
KeyboardNavigation.AcceptsReturn="False"
Style="{StaticResource MaterialDesignOutlinedButton}"
ToolTip="This will rollback the application to previous version 3.4.6.0321. All changes since installing the latest v4.0.0 update will be lost."
Visibility="{Binding IsRollBackCommandVisible, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}" />-->
</WrapPanel> </WrapPanel>
<!-- About --> <!-- About -->

View file

@ -180,6 +180,40 @@
<TextBlock Style="{StaticResource TextBlockLabel}">Automatically close the application when exiting MSFS.</TextBlock> <TextBlock Style="{StaticResource TextBlockLabel}">Automatically close the application when exiting MSFS.</TextBlock>
</WrapPanel> </WrapPanel>
</WrapPanel> </WrapPanel>
<WrapPanel
Width="Auto"
Margin="0,0,20,20"
Orientation="Vertical">
<TextBlock Style="{StaticResource TextBlockHeading}">Folder Path to Store POPM Configuration and Profiles</TextBlock>
<Line
Stretch="Fill"
Stroke="Gray"
X2="1" />
<WrapPanel>
<ComboBox
Width="200"
Margin="20,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
SelectedValue="{Binding AppSettingData.ApplicationSetting.GeneralSetting.UseApplicationDataPath, Mode=TwoWay}"
SelectedValuePath="Tag">
<ComboBoxItem Content="Documents folder (Default)" Tag="False" />
<ComboBoxItem Content="AppData Roaming folder" Tag="True" />
</ComboBox>
<TextBlock Margin="30,5,0,0" FontSize="12">
<Hyperlink
NavigateUri="{Binding AppSettingData.ApplicationSetting.GeneralSetting.ApplicationDataPath}"
RequestNavigate="Hyperlink_OpenDataFolder"
Style="{StaticResource MaterialDesignBody2Hyperlink}"
TextDecorations="Underline">
<TextBlock
Margin="0,0,0,0"
FontSize="12"
Text="{Binding AppSettingData.ApplicationSetting.GeneralSetting.ApplicationDataPath}" />
</Hyperlink>
</TextBlock>
</WrapPanel>
</WrapPanel>
<WrapPanel Margin="0,0,20,20" Orientation="Vertical"> <WrapPanel Margin="0,0,20,20" Orientation="Vertical">
<TextBlock Style="{StaticResource TextBlockHeading}">Turbo Mode</TextBlock> <TextBlock Style="{StaticResource TextBlockHeading}">Turbo Mode</TextBlock>
<Line <Line
@ -630,31 +664,29 @@
</WrapPanel> </WrapPanel>
<!-- Dynamic LOD Settings --> <!-- Dynamic LOD Settings -->
<WrapPanel Visibility="{c:Binding LocalCompileOnly}"> <WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryDynamicLodSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryDynamicLodSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}"> <WrapPanel Margin="0,0,20,20" Orientation="Vertical">
<WrapPanel Margin="0,0,20,20" Orientation="Vertical"> <WrapPanel>
<WrapPanel> <TextBlock
<TextBlock Padding="0,0,5,0"
Padding="0,0,5,0" Foreground="Red"
Foreground="Red" Style="{StaticResource TextBlockHeading}">
Style="{StaticResource TextBlockHeading}"> (Unsupported Feature)
(Unsupported Feature) </TextBlock>
</TextBlock> <TextBlock Style="{StaticResource TextBlockHeading}">Dynamically adjust Terrain and Object Level of Details</TextBlock>
<TextBlock Style="{StaticResource TextBlockHeading}">Dynamically adjust Terrain and Object Level of Details</TextBlock> </WrapPanel>
</WrapPanel> <Line
<Line Stretch="Fill"
Stretch="Fill" Stroke="Gray"
Stroke="Gray" X2="1" />
X2="1" /> <WrapPanel>
<WrapPanel> <ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" /> <TextBlock Style="{StaticResource TextBlockLabel}">
<TextBlock Style="{StaticResource TextBlockLabel}"> Enable automatic adjustments of TLOD and OLOD to get the desired targeted frame rate (FPS).
Enable automatic adjustments of TLOD and OLOD to get the desired targeted frame rate (FPS). </TextBlock>
</TextBlock> </WrapPanel>
</WrapPanel> <WrapPanel Visibility="{Binding Path=AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
<WrapPanel Visibility="{Binding Path=AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}"> <appUserControl:DynamicLodPreference />
<appUserControl:DynamicLodPreference />
</WrapPanel>
</WrapPanel> </WrapPanel>
</WrapPanel> </WrapPanel>
</WrapPanel> </WrapPanel>

View file

@ -1,7 +1,10 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using MSFSPopoutPanelManager.MainApp.ViewModel; using MSFSPopoutPanelManager.MainApp.ViewModel;
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Navigation;
namespace MSFSPopoutPanelManager.MainApp.AppUserControl namespace MSFSPopoutPanelManager.MainApp.AppUserControl
{ {
@ -22,5 +25,11 @@ namespace MSFSPopoutPanelManager.MainApp.AppUserControl
InitializeComponent(); InitializeComponent();
}; };
} }
private void Hyperlink_OpenDataFolder(object sender, RequestNavigateEventArgs e)
{
// ToDo: check for folder existence
Process.Start("explorer.exe",e.Uri.ToString());
}
} }
} }

View file

@ -14,14 +14,27 @@
mc:Ignorable="d"> mc:Ignorable="d">
<Window.Resources> <Window.Resources>
<Style TargetType="{x:Type Button}"> <Style TargetType="{x:Type Button}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="14" /> <Setter Property="FontSize" Value="14" />
<Setter Property="FontWeight" Value="Bold" /> <Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="White" /> <Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="Transparent" /> <Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border
Background="{TemplateBinding Background}"
BorderBrush="Gray"
BorderThickness="1">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Transparent" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<EventSetter Event="Click" Handler="Button_Click" /> <EventSetter Event="Click" Handler="Button_Click" />
</Style> </Style>
</Window.Resources> </Window.Resources>

View file

@ -13,7 +13,7 @@ namespace MSFSPopoutPanelManager.MainApp.AppWindow
{ {
private readonly NumPadViewModel _viewModel; private readonly NumPadViewModel _viewModel;
public NumPad(Guid panelId) public NumPad(Guid panelId, int initialWidth, int initialHeight)
{ {
InitializeComponent(); InitializeComponent();
if (DesignerProperties.GetIsInDesignMode(new DependencyObject())) if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
@ -30,8 +30,19 @@ namespace MSFSPopoutPanelManager.MainApp.AppWindow
throw new ApplicationException("Unable to instantiate NumPad window"); throw new ApplicationException("Unable to instantiate NumPad window");
_viewModel.PanelConfig.PanelHandle = new WindowInteropHelper(window).Handle; _viewModel.PanelConfig.PanelHandle = new WindowInteropHelper(window).Handle;
_viewModel.PanelConfig.Width = Convert.ToInt32(Width);
_viewModel.PanelConfig.Height = Convert.ToInt32(Height); if (initialWidth == 0 && initialHeight == 0)
{
this.Width = 300;
this.Height = 400;
_viewModel.PanelConfig.Width = Convert.ToInt16(this.Width);
_viewModel.PanelConfig.Height = Convert.ToInt32(this.Height);
}
else
{
this.Width = initialWidth;
this.Height = initialHeight;
}
}; };
this.MouseLeftButtonDown += NumPad_MouseLeftButtonDown; this.MouseLeftButtonDown += NumPad_MouseLeftButtonDown;

View file

@ -41,18 +41,5 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
get => SharedStorage.ApplicationWindow; get => SharedStorage.ApplicationWindow;
set => SharedStorage.ApplicationWindow = value; set => SharedStorage.ApplicationWindow = value;
} }
public bool LocalCompileOnly
{
get
{
#if LOCAL
return true;
#endif
return false;
}
}
} }
} }

View file

@ -16,8 +16,6 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
public ICommand DeleteAppCacheCommand { get; private set; } public ICommand DeleteAppCacheCommand { get; private set; }
public ICommand RollBackCommand { get; private set; }
public string ApplicationVersion { get; private set; } public string ApplicationVersion { get; private set; }
public bool IsRollBackCommandVisible { get; private set; } public bool IsRollBackCommandVisible { get; private set; }
@ -30,7 +28,6 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
HyperLinkCommand = new DelegateCommand<string>(OnHyperLinkActivated); HyperLinkCommand = new DelegateCommand<string>(OnHyperLinkActivated);
DeleteAppCacheCommand = new DelegateCommand(OnDeleteAppCache); DeleteAppCacheCommand = new DelegateCommand(OnDeleteAppCache);
RollBackCommand = new DelegateCommand(OnRollBack);
#if DEBUG #if DEBUG
var buildConfig = " (Debug)"; var buildConfig = " (Debug)";
@ -41,8 +38,6 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
#endif #endif
ApplicationVersion = $"{WindowProcessManager.GetApplicationVersion()}{buildConfig}"; ApplicationVersion = $"{WindowProcessManager.GetApplicationVersion()}{buildConfig}";
IsRollBackCommandVisible = _helpOrchestrator.IsRollBackUpdateEnabled();
HasOrphanAppCache = _helpOrchestrator.HasOrphanAppCache(); HasOrphanAppCache = _helpOrchestrator.HasOrphanAppCache();
} }
@ -68,9 +63,6 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
case "Version Info": case "Version Info":
_helpOrchestrator.OpenVersionInfo(); _helpOrchestrator.OpenVersionInfo();
break; break;
case "Open Data Folder":
_helpOrchestrator.OpenDataFolder();
break;
case "Download VCC Library": case "Download VCC Library":
_helpOrchestrator.DownloadVccLibrary(); _helpOrchestrator.DownloadVccLibrary();
break; break;
@ -82,15 +74,5 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
_helpOrchestrator.DeleteAppCache(); _helpOrchestrator.DeleteAppCache();
HasOrphanAppCache = _helpOrchestrator.HasOrphanAppCache(); HasOrphanAppCache = _helpOrchestrator.HasOrphanAppCache();
} }
private async void OnRollBack()
{
var result = await DialogHost.Show(new ConfirmationDialog($"WARNING!{Environment.NewLine}Are you sure you want to rollback to previous version of Pop Out Panel Manager (v3.4.6.0321)? All your changes since updated to v4.0.0 will be lost. Backups of user profile and application settings file from previous version of the application will be restored.", "Rollback"), "RootDialog");
if (result != null && result.Equals("CONFIRM"))
{
_helpOrchestrator.RollBackUpdate();
}
}
} }
} }

View file

@ -87,7 +87,7 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
{ {
Application.Current.Dispatcher.Invoke(async () => Application.Current.Dispatcher.Invoke(async () =>
{ {
var numPad = new NumPad(panelConfig.Id); var numPad = new NumPad(panelConfig.Id, panelConfig.Width, panelConfig.Height);
numPad.Show(); numPad.Show();
await Task.Run(() => await Task.Run(() =>

View file

@ -228,8 +228,8 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
PanelType = PanelType.NumPadWindow, PanelType = PanelType.NumPadWindow,
Left = 0, Left = 0,
Top = 0, Top = 0,
Width = 1920, Width = 0,
Height = 40, Height = 0,
AutoGameRefocus = false AutoGameRefocus = false
}); });
} }

View file

@ -41,6 +41,25 @@ namespace MSFSPopoutPanelManager.Orchestration
Task.Run(() => _flightSimOrchestrator.StartSimConnectServer()); // Start the SimConnect server Task.Run(() => _flightSimOrchestrator.StartSimConnectServer()); // Start the SimConnect server
_keyboardOrchestrator.Initialize(); _keyboardOrchestrator.Initialize();
AppSettingData.ApplicationSetting.GeneralSetting.OnApplicationDataPathUpdated += (_, e) =>
{
AppSettingDataManager.MoveAppSettings(AppSettingData.ApplicationSetting);
ProfileDataManager.MoveProfiles(ProfileData.Profiles, e);
FileLogger.UseApplicationDataPath = e;
try
{
FileLogger.CloseFileLogger();
if (Directory.Exists(FileIo.GetUserDataFilePath(!e)))
Directory.Delete(FileIo.GetUserDataFilePath(!e), true);
}
catch
{
FileLogger.WriteLog($"Unable to remove old POPM data folder. {FileIo.GetUserDataFilePath(!e)}", StatusMessageType.Error);
}
};
} }
public void ApplicationClose() public void ApplicationClose()
@ -56,7 +75,7 @@ namespace MSFSPopoutPanelManager.Orchestration
private void CheckForAutoUpdate() private void CheckForAutoUpdate()
{ {
var jsonPath = Path.Combine(Path.Combine(FileIo.GetUserDataFilePath(), "autoupdate.json")); var jsonPath = Path.Combine(Path.Combine(FileIo.GetUserDataFilePath(AppSettingData.ApplicationSetting.GeneralSetting.UseApplicationDataPath), "autoupdate.json"));
AutoUpdater.PersistenceProvider = new JsonFilePersistenceProvider(jsonPath); AutoUpdater.PersistenceProvider = new JsonFilePersistenceProvider(jsonPath);
AutoUpdater.Synchronous = true; AutoUpdater.Synchronous = true;
AutoUpdater.AppTitle = "MSFS Pop Out Panel Manager"; AutoUpdater.AppTitle = "MSFS Pop Out Panel Manager";

View file

@ -1,8 +1,8 @@
using System; using MSFSPopoutPanelManager.DomainModel.DataFile;
using MSFSPopoutPanelManager.DomainModel.DataFile;
using MSFSPopoutPanelManager.DomainModel.Setting; using MSFSPopoutPanelManager.DomainModel.Setting;
using MSFSPopoutPanelManager.Shared; using MSFSPopoutPanelManager.Shared;
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@ -18,10 +18,30 @@ namespace MSFSPopoutPanelManager.Orchestration
{ {
Debug.WriteLine("Reading application settings data file..."); Debug.WriteLine("Reading application settings data file...");
using var reader = new StreamReader(Path.Combine(FileIo.GetUserDataFilePath(), APP_SETTING_DATA_FILENAME)); // Try to read folder path from both locations
var documentsFolderPath = Path.Combine(FileIo.GetUserDataFilePath(false), APP_SETTING_DATA_FILENAME);
var applicationDataFolderPath = Path.Combine(FileIo.GetUserDataFilePath(true), APP_SETTING_DATA_FILENAME);
string folderPath;
if (File.Exists(applicationDataFolderPath))
{
folderPath = applicationDataFolderPath;
FileLogger.UseApplicationDataPath = true;
}
else
{
folderPath = documentsFolderPath;
FileLogger.UseApplicationDataPath = false;
}
using var reader = new StreamReader(folderPath);
var fileContent = reader.ReadToEnd(); var fileContent = reader.ReadToEnd();
return JsonConvert.DeserializeObject<AppSettingFile>(fileContent).ApplicationSetting; var appSetting = JsonConvert.DeserializeObject<AppSettingFile>(fileContent).ApplicationSetting;
appSetting.GeneralSetting.UseApplicationDataPath = folderPath.IndexOf("Roaming", StringComparison.Ordinal) > -1;
return appSetting;
} }
catch catch
{ {
@ -33,24 +53,44 @@ namespace MSFSPopoutPanelManager.Orchestration
{ {
try try
{ {
Debug.WriteLine("Saving application settings data file..."); CreateAppSettings(appSetting);
var dataFilePath = FileIo.GetUserDataFilePath();
if (string.IsNullOrEmpty(dataFilePath))
throw new Exception("Unable to get app setting data file path.");
if (!Directory.Exists(dataFilePath))
Directory.CreateDirectory(dataFilePath);
using var file = File.CreateText(Path.Combine(dataFilePath, APP_SETTING_DATA_FILENAME));
var serializer = new JsonSerializer();
serializer.Serialize(file, new AppSettingFile { ApplicationSetting = appSetting });
} }
catch catch
{ {
FileLogger.WriteLog($"Unable to write app setting data file: {APP_SETTING_DATA_FILENAME}", StatusMessageType.Error); FileLogger.WriteLog($"Unable to write app setting data file: {APP_SETTING_DATA_FILENAME}", StatusMessageType.Error);
} }
} }
public static void MoveAppSettings(ApplicationSetting appSetting)
{
try
{
CreateAppSettings(appSetting);
// Remove file in old path
var oldPath = FileIo.GetUserDataFilePath(!appSetting.GeneralSetting.UseApplicationDataPath);
if (File.Exists(oldPath))
File.Delete(oldPath);
}
catch
{
FileLogger.WriteLog($"Unable to remove old app setting data folder:", StatusMessageType.Error);
}
}
private static void CreateAppSettings(ApplicationSetting appSetting)
{
var dataFilePath = FileIo.GetUserDataFilePath(appSetting.GeneralSetting.UseApplicationDataPath);
if (string.IsNullOrEmpty(dataFilePath))
throw new Exception("Unable to get app setting data file path.");
if (!Directory.Exists(dataFilePath))
Directory.CreateDirectory(dataFilePath);
using var file = File.CreateText(Path.Combine(dataFilePath, APP_SETTING_DATA_FILENAME));
var serializer = new JsonSerializer();
serializer.Serialize(file, new AppSettingFile { ApplicationSetting = appSetting });
}
} }
} }

View file

@ -3,10 +3,8 @@ using MSFSPopoutPanelManager.DomainModel.Setting;
using MSFSPopoutPanelManager.Shared; using MSFSPopoutPanelManager.Shared;
using MSFSPopoutPanelManager.SimConnectAgent; using MSFSPopoutPanelManager.SimConnectAgent;
using MSFSPopoutPanelManager.WindowsAgent; using MSFSPopoutPanelManager.WindowsAgent;
using Newtonsoft.Json.Linq;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Dynamic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace MSFSPopoutPanelManager.Orchestration namespace MSFSPopoutPanelManager.Orchestration

View file

@ -39,11 +39,6 @@ namespace MSFSPopoutPanelManager.Orchestration
Process.Start("notepad.exe", "VERSION.md"); Process.Start("notepad.exe", "VERSION.md");
} }
public void OpenDataFolder()
{
Process.Start("explorer.exe", Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MSFS Pop Out Panel Manager"));
}
public bool HasOrphanAppCache() public bool HasOrphanAppCache()
{ {
var appLocal = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); var appLocal = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
@ -104,35 +99,5 @@ namespace MSFSPopoutPanelManager.Orchestration
FileLogger.WriteLog("Delete app cache exception: " + ex.Message, StatusMessageType.Error); FileLogger.WriteLog("Delete app cache exception: " + ex.Message, StatusMessageType.Error);
} }
} }
public void RollBackUpdate()
{
var userProfileBackupPath = Path.Combine(FileIo.GetUserDataFilePath(), "Backup-previous-version", "userprofiledata.json");
var appSettingBackupPath = Path.Combine(FileIo.GetUserDataFilePath(), "Backup-previous-version", "appsettingdata.json");
var userProfilePath = Path.Combine(FileIo.GetUserDataFilePath(), "userprofiledata.json");
var appSettingPath = Path.Combine(FileIo.GetUserDataFilePath(), "appsettingdata.json");
if (File.Exists(userProfileBackupPath))
File.Copy(userProfileBackupPath, userProfilePath, true);
if (File.Exists(appSettingBackupPath))
File.Copy(appSettingBackupPath, appSettingPath, true);
AutoUpdater.InstalledVersion = new Version("1.0.0.0");
AutoUpdater.Synchronous = true;
AutoUpdater.AppTitle = "MSFS Pop Out Panel Manager";
AutoUpdater.RunUpdateAsAdmin = false;
AutoUpdater.UpdateFormSize = new System.Drawing.Size(1024, 660);
AutoUpdater.UpdateMode = Mode.ForcedDownload;
AutoUpdater.Start("https://raw.githubusercontent.com/hawkeye-stan/msfs-popout-panel-manager/master/rollback.xml");
}
public bool IsRollBackUpdateEnabled()
{
var appSettingBackupPath = Path.Combine(FileIo.GetUserDataFilePath(), "Backup-previous-version", "appsettingdata.json");
return File.Exists(appSettingBackupPath);
}
} }
} }

View file

@ -69,9 +69,13 @@ namespace MSFSPopoutPanelManager.Orchestration
{ {
Debug.WriteLine("Ends Global Keyboard Hook (Forced)"); Debug.WriteLine("Ends Global Keyboard Hook (Forced)");
_keyPressCaptureList = new List<string>(); _keyPressCaptureList = new List<string>();
_globalKeyboardHook.OnKeyboardPressed -= HandleGlobalKeyboardHookOnKeyboardPressed;
_globalKeyboardHook?.Dispose(); if (_globalKeyboardHook != null)
_globalKeyboardHook = null; {
_globalKeyboardHook.OnKeyboardPressed -= HandleGlobalKeyboardHookOnKeyboardPressed;
_globalKeyboardHook?.Dispose();
_globalKeyboardHook = null;
}
} }
private void HandleGlobalKeyboardHookOnKeyboardPressed(object sender, GlobalKeyboardHookEventArgs e) private void HandleGlobalKeyboardHookOnKeyboardPressed(object sender, GlobalKeyboardHookEventArgs e)

View file

@ -209,7 +209,7 @@ namespace MSFSPopoutPanelManager.Orchestration
foreach (var panel in panels) foreach (var panel in panels)
{ {
if (!panel.FloatingPanel.IsEnabled || panel.FullScreen) if (!panel.FloatingPanel.IsEnabled)
return; return;
if (panel.PanelType is not (PanelType.CustomPopout or PanelType.BuiltInPopout)) if (panel.PanelType is not (PanelType.CustomPopout or PanelType.BuiltInPopout))

View file

@ -19,7 +19,7 @@ namespace MSFSPopoutPanelManager.Orchestration
internal FlightSimData FlightSimDataRef { private get; set; } internal FlightSimData FlightSimDataRef { private get; set; }
[IgnorePropertyChanged] [IgnorePropertyChanged]
internal AppSettingData AppSettingDataRef { private get; set; } public AppSettingData AppSettingDataRef { private get; set; }
public void AddProfile(string profileName) public void AddProfile(string profileName)
{ {
@ -29,7 +29,7 @@ namespace MSFSPopoutPanelManager.Orchestration
Profiles.Add(newProfile); Profiles.Add(newProfile);
SetActiveProfile(newProfile.Id); SetActiveProfile(newProfile.Id);
ProfileDataManager.WriteProfiles(Profiles); ProfileDataManager.WriteProfiles(Profiles, AppSettingDataRef.ApplicationSetting.GeneralSetting.UseApplicationDataPath);
AppSettingDataRef.ApplicationSetting.SystemSetting.LastUsedProfileId = newProfile.Id; AppSettingDataRef.ApplicationSetting.SystemSetting.LastUsedProfileId = newProfile.Id;
} }
@ -64,7 +64,7 @@ namespace MSFSPopoutPanelManager.Orchestration
Profiles.Add(newProfile); Profiles.Add(newProfile);
SetActiveProfile(newProfile.Id); SetActiveProfile(newProfile.Id);
ProfileDataManager.WriteProfiles(Profiles); ProfileDataManager.WriteProfiles(Profiles, AppSettingDataRef.ApplicationSetting.GeneralSetting.UseApplicationDataPath);
AppSettingDataRef.ApplicationSetting.SystemSetting.LastUsedProfileId = newProfile.Id; AppSettingDataRef.ApplicationSetting.SystemSetting.LastUsedProfileId = newProfile.Id;
} }
@ -99,7 +99,7 @@ namespace MSFSPopoutPanelManager.Orchestration
ActiveProfile.AircraftBindings.Add(aircraft); ActiveProfile.AircraftBindings.Add(aircraft);
ProfileDataManager.WriteProfiles(Profiles); ProfileDataManager.WriteProfiles(Profiles, AppSettingDataRef.ApplicationSetting.GeneralSetting.UseApplicationDataPath);
RefreshProfile(); RefreshProfile();
} }
@ -110,13 +110,13 @@ namespace MSFSPopoutPanelManager.Orchestration
ActiveProfile.AircraftBindings.Remove(aircraft); ActiveProfile.AircraftBindings.Remove(aircraft);
ProfileDataManager.WriteProfiles(Profiles); ProfileDataManager.WriteProfiles(Profiles, AppSettingDataRef.ApplicationSetting.GeneralSetting.UseApplicationDataPath);
RefreshProfile(); RefreshProfile();
} }
public void ReadProfiles() public void ReadProfiles()
{ {
Profiles = new SortedObservableCollection<UserProfile>(ProfileDataManager.ReadProfiles()); Profiles = new SortedObservableCollection<UserProfile>(ProfileDataManager.ReadProfiles(AppSettingDataRef.ApplicationSetting.GeneralSetting.UseApplicationDataPath));
Profiles.ToList().ForEach(p => p.OnProfileChanged += (_, _) => WriteProfiles()); Profiles.ToList().ForEach(p => p.OnProfileChanged += (_, _) => WriteProfiles());
// Detect profiles collection changes // Detect profiles collection changes
@ -135,7 +135,7 @@ namespace MSFSPopoutPanelManager.Orchestration
public void WriteProfiles() public void WriteProfiles()
{ {
Debug.WriteLine("Saving Data ... "); Debug.WriteLine("Saving Data ... ");
ProfileDataManager.WriteProfiles(Profiles); ProfileDataManager.WriteProfiles(Profiles, AppSettingDataRef.ApplicationSetting.GeneralSetting.UseApplicationDataPath);
} }
public void SetActiveProfile(Guid id) public void SetActiveProfile(Guid id)

View file

@ -13,13 +13,13 @@ namespace MSFSPopoutPanelManager.Orchestration
{ {
private const string USER_PROFILE_DATA_FILENAME = "userprofiledata.json"; private const string USER_PROFILE_DATA_FILENAME = "userprofiledata.json";
public static IList<UserProfile> ReadProfiles() public static IList<UserProfile> ReadProfiles(bool isRoamingPath)
{ {
try try
{ {
Debug.WriteLine("Reading user profile data file..."); Debug.WriteLine("Reading user profile data file...");
using var reader = new StreamReader(Path.Combine(FileIo.GetUserDataFilePath(), USER_PROFILE_DATA_FILENAME)); using var reader = new StreamReader(Path.Combine(FileIo.GetUserDataFilePath(isRoamingPath), USER_PROFILE_DATA_FILENAME));
var fileContent = reader.ReadToEnd(); var fileContent = reader.ReadToEnd();
return JsonConvert.DeserializeObject<UserProfileFile>(fileContent).Profiles; return JsonConvert.DeserializeObject<UserProfileFile>(fileContent).Profiles;
@ -30,7 +30,7 @@ namespace MSFSPopoutPanelManager.Orchestration
} }
} }
public static void WriteProfiles(IList<UserProfile> profiles) public static void WriteProfiles(IList<UserProfile> profiles, bool isRoamingPath)
{ {
if (profiles == null) if (profiles == null)
{ {
@ -40,22 +40,44 @@ namespace MSFSPopoutPanelManager.Orchestration
try try
{ {
var dataFilePath = FileIo.GetUserDataFilePath(); CreateProfiles(profiles, isRoamingPath);
if (string.IsNullOrEmpty(dataFilePath))
throw new Exception("Unable to get user profile dat file path.");
if (!Directory.Exists(dataFilePath))
Directory.CreateDirectory(dataFilePath);
using var file = File.CreateText(Path.Combine(dataFilePath, USER_PROFILE_DATA_FILENAME));
var serializer = new JsonSerializer();
serializer.Serialize(file, new UserProfileFile { Profiles = profiles });
} }
catch catch
{ {
FileLogger.WriteLog($"Unable to write user data file: {USER_PROFILE_DATA_FILENAME}", StatusMessageType.Error); FileLogger.WriteLog($"Unable to write user data file: {USER_PROFILE_DATA_FILENAME}", StatusMessageType.Error);
} }
} }
public static void MoveProfiles(IList<UserProfile> profiles, bool isRoamingPath)
{
try
{
CreateProfiles(profiles, isRoamingPath);
// Remove file in old path
var oldPath = FileIo.GetUserDataFilePath(!isRoamingPath);
if (File.Exists(oldPath))
File.Delete(oldPath);
}
catch
{
FileLogger.WriteLog($"Unable to move user data file: {USER_PROFILE_DATA_FILENAME}", StatusMessageType.Error);
}
}
private static void CreateProfiles(IList<UserProfile> profiles, bool isRoamingPath)
{
var dataFilePath = FileIo.GetUserDataFilePath(isRoamingPath);
if (string.IsNullOrEmpty(dataFilePath))
throw new Exception("Unable to get user profile data file path.");
if (!Directory.Exists(dataFilePath))
Directory.CreateDirectory(dataFilePath);
using var file = File.CreateText(Path.Combine(dataFilePath, USER_PROFILE_DATA_FILENAME));
var serializer = new JsonSerializer();
serializer.Serialize(file, new UserProfileFile { Profiles = profiles });
}
} }
} }

View file

@ -171,3 +171,5 @@ Thank you for your super kind support of this app!
[WPF CalcBinding](https://github.com/Alex141/CalcBinding) by Alexander Zinchenko [WPF CalcBinding](https://github.com/Alex141/CalcBinding) by Alexander Zinchenko
[AutoUpdater.NET](https://github.com/ravibpatel/AutoUpdater.NET) by Ravi Patel [AutoUpdater.NET](https://github.com/ravibpatel/AutoUpdater.NET) by Ravi Patel
[DynamicLOD](https://github.com/Fragtality/DynamicLOD_ by Fragtality (idea and MSFS memory access code)

View file

@ -1,19 +1,15 @@
## Version 4.1.0 ## Version 4.1.1
* Added new method to select panel source for an aircraft profile using fixed camera view instead of relying saved custom camera view. Previous method of using saved custom camera view is still available to use if desire. * Added option to store POPM profiles and configuration files in your user's AppData Roaming folder instead of Documents folder. Hopefully, this solved the issue where OneDrive users are having issue with POPM files.
Video showing how to create a new aircraft profile using the new panel selection method: https://vimeo.com/917361559 * Fixed POPM inability to close correctly when Keyboard Shortcuts preference is disabled.
Video showing how to update existing aircraft profile to use the new panel selection method: https://vimeo.com/917364912 * Fixed issue where auto start option failed to retain CommandLine arguments in exe.xml file.
* Added new virtual number pad to be used for touch enabled screen. This number pad will first focus the game window before sending num pad keystroke to the game. * Fixed issue where auto start does not work correctly for Steam version of MSFS since exe.xml file location has been moved by Steam installation.
* Added new feature to allow pop up panel as floating window. You can assign hotkeys (Ctrl-0 to Ctrl-9) to have the pop out to toggle either showing on screen or minimize. * Added ability for full screen panel to work as floating panel. An example use case is to show and hide EFB as full screen using keyboard shortcut.
Video showing how to manage floating panel: https://vimeo.com/918153200 * Added dynamic LOD (my own implementation of AutoFPS) - this is totally experimental and unsupported. If you decide to use this version of dynamic LOD, you don't have to run multiple apps.
* Added a new button to easily close all Pop Out Panel Manager's managed pop outs. * Fixed various smaller bugs.
* Updated keyboard shortcut feature in preference setting to allow usage of custom keyboard shortcut instead of predefined set of keyboard shortcuts.
* Fixed few reported bugs in the application.

View file

@ -5,47 +5,38 @@ namespace MSFSPopoutPanelManager.Shared
{ {
public class FileIo public class FileIo
{ {
public static string GetUserDataFilePath() public static string GetUserDataFilePath(bool isRoamingPath)
{ {
#if DEBUG var specialFolder = isRoamingPath ? Environment.SpecialFolder.ApplicationData : Environment.SpecialFolder.MyDocuments;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MSFS Pop Out Panel Manager Debug"); return Path.Combine(Environment.GetFolderPath(specialFolder), GetBuildConfigPath());
#elif LOCAL
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MSFS Pop Out Panel Manager Local");
#else
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MSFS Pop Out Panel Manager");
#endif
} }
public static string GetErrorLogFilePath() public static string GetErrorLogFilePath(bool isRoamingPath)
{ {
#if DEBUG var specialFolder = isRoamingPath ? Environment.SpecialFolder.ApplicationData : Environment.SpecialFolder.MyDocuments;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"MSFS Pop Out Panel Manager Debug\LogFiles\error.log"); return Path.Combine(Environment.GetFolderPath(specialFolder), GetBuildConfigPath(), @"LogFiles\error.log");
#elif LOCAL
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"MSFS Pop Out Panel Manager Local\LogFiles\error.log");
#else
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"MSFS Pop Out Panel Manager\LogFiles\error.log");
#endif
} }
public static string GetDebugLogFilePath() public static string GetDebugLogFilePath(bool isRoamingPath)
{ {
#if DEBUG var specialFolder = isRoamingPath ? Environment.SpecialFolder.ApplicationData : Environment.SpecialFolder.MyDocuments;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"MSFS Pop Out Panel Manager Debug\LogFiles\debug.log"); return Path.Combine(Environment.GetFolderPath(specialFolder), GetBuildConfigPath(), @"LogFiles\debug.log");
#elif LOCAL
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"MSFS Pop Out Panel Manager Local\LogFiles\debug.log");
#else
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"MSFS Pop Out Panel Manager\LogFiles\debug.log");
#endif
} }
public static string GetInfoLogFilePath() public static string GetInfoLogFilePath(bool isRoamingPath)
{
var specialFolder = isRoamingPath ? Environment.SpecialFolder.ApplicationData : Environment.SpecialFolder.MyDocuments;
return Path.Combine(Environment.GetFolderPath(specialFolder), GetBuildConfigPath(), @"LogFiles\info.log");
}
private static string GetBuildConfigPath()
{ {
#if DEBUG #if DEBUG
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"MSFS Pop Out Panel Manager Debug\LogFiles\info.log"); return "MSFS Pop Out Panel Manager Debug";
#elif LOCAL #elif LOCAL
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"MSFS Pop Out Panel Manager Local\LogFiles\info.log"); return "MSFS Pop Out Panel Manager Local";
#else #else
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"MSFS Pop Out Panel Manager\LogFiles\info.log"); return "MSFS Pop Out Panel Manager";
#endif #endif
} }
} }

View file

@ -24,18 +24,12 @@ namespace MSFSPopoutPanelManager.Shared
if (LogManager.GetRepository(Assembly.GetEntryAssembly()).GetAppenders().First() is not RollingFileAppender errorLogAppender) if (LogManager.GetRepository(Assembly.GetEntryAssembly()).GetAppenders().First() is not RollingFileAppender errorLogAppender)
return; return;
errorLogAppender.File = FileIo.GetErrorLogFilePath(); errorLogAppender.File = FileIo.GetErrorLogFilePath(UseApplicationDataPath);
errorLogAppender.ActivateOptions(); errorLogAppender.ActivateOptions();
//var infoLogAppender = LogManager.GetRepository(Assembly.GetEntryAssembly()).GetAppenders().Skip(1).First() as RollingFileAppender;
//infoLogAppender.File = FileIo.GetInfoLogFilePath();
//infoLogAppender.ActivateOptions();
//var debugLogAppender = LogManager.GetRepository(Assembly.GetEntryAssembly()).GetAppenders().Skip(2).First() as RollingFileAppender;
//debugLogAppender.File = FileIo.GetDebugLogFilePath();
//debugLogAppender.ActivateOptions();
} }
public static bool UseApplicationDataPath { get; set; } = false;
public static void WriteLog(string message, StatusMessageType messageType) public static void WriteLog(string message, StatusMessageType messageType)
{ {
switch (messageType) switch (messageType)
@ -43,12 +37,12 @@ namespace MSFSPopoutPanelManager.Shared
case StatusMessageType.Error: case StatusMessageType.Error:
Log.Error(message); Log.Error(message);
break; break;
//case StatusMessageType.Info: //case StatusMessageType.Info:
// Log.Info(message); // Log.Info(message);
// break; // break;
//case StatusMessageType.Debug: //case StatusMessageType.Debug:
// Log.Debug(message); // Log.Debug(message);
// break; // break;
} }
} }
@ -56,5 +50,10 @@ namespace MSFSPopoutPanelManager.Shared
{ {
Log.Error(message, exception); Log.Error(message, exception);
} }
public static void CloseFileLogger()
{
LogManager.ShutdownRepository();
}
} }
} }

View file

@ -1,6 +1,22 @@
# Version History # Version History
<hr/> <hr/>
## Version 4.1.1
* Added option to store POPM profiles and configuration files in your user's AppData Roaming folder instead of Documents folder. Hopefully, this solved the issue where OneDrive users are having issue with POPM files.
* Fixed POPM inability to close correctly when Keyboard Shortcuts preference is disabled.
* Fixed issue where auto start option failed to retain CommandLine arguments in exe.xml file.
* Fixed issue where auto start does not work correctly for Steam version of MSFS since exe.xml file location has been moved by Steam installation.
* Added ability for full screen panel to work as floating panel. An example use case is to show and hide EFB as full screen using keyboard shortcut.
* Added dynamic LOD (my own implementation of AutoFPS) - this is totally experimental and unsupported. If you decide to use this version of dynamic LOD, you don't have to run multiple apps.
* Fixed various smaller bugs.
## Version 4.1.0 ## Version 4.1.0
* Added new method to select panel source for an aircraft profile using fixed camera view instead of relying saved custom camera view. Previous method of using saved custom camera view is still available to use if desire. * Added new method to select panel source for an aircraft profile using fixed camera view instead of relying saved custom camera view. Previous method of using saved custom camera view is still available to use if desire.