1
0
Fork 0
mirror of https://github.com/hawkeye-stan/msfs-popout-panel-manager.git synced 2024-12-26 22:32:01 +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()
{
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))
return filePathMsStore + "exe.xml";
@ -187,5 +187,8 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
[XmlElement(ElementName = "Path")]
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 FpsTolerance { get; set; } = 5;
public int FpsTolerance { get; set; } = 4;
public bool TlodMinOnGround { get; set; } = true;
@ -31,13 +31,13 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
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 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;

View file

@ -1,4 +1,5 @@
using MSFSPopoutPanelManager.Shared;
using System;
using MSFSPopoutPanelManager.Shared;
using Newtonsoft.Json;
namespace MSFSPopoutPanelManager.DomainModel.Setting
@ -8,6 +9,17 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
public GeneralSetting()
{
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;
@ -22,6 +34,8 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
public bool TurboMode { get; set; } = false;
public bool UseApplicationDataPath { get; set; } = false;
[JsonIgnore, IgnorePropertyChanged]
public bool AutoStart
{
@ -34,5 +48,10 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
AppAutoStart.Deactivate();
}
}
[JsonIgnore]
public string ApplicationDataPath { get; set; }
public event EventHandler<bool> OnApplicationDataPathUpdated;
}
}

View file

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

View file

@ -247,14 +247,6 @@
Stroke="Gray"
X2="1" />
</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">
<Hyperlink
NavigateUri="Download VCC Library"
@ -273,16 +265,6 @@
KeyboardNavigation.AcceptsReturn="False"
Style="{StaticResource MaterialDesignOutlinedButton}"
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>
<!-- About -->

View file

@ -180,6 +180,40 @@
<TextBlock Style="{StaticResource TextBlockLabel}">Automatically close the application when exiting MSFS.</TextBlock>
</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">
<TextBlock Style="{StaticResource TextBlockHeading}">Turbo Mode</TextBlock>
<Line
@ -630,31 +664,29 @@
</WrapPanel>
<!-- Dynamic LOD Settings -->
<WrapPanel Visibility="{c:Binding LocalCompileOnly}">
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryDynamicLodSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
<WrapPanel>
<TextBlock
Padding="0,0,5,0"
Foreground="Red"
Style="{StaticResource TextBlockHeading}">
(Unsupported Feature)
</TextBlock>
<TextBlock Style="{StaticResource TextBlockHeading}">Dynamically adjust Terrain and Object Level of Details</TextBlock>
</WrapPanel>
<Line
Stretch="Fill"
Stroke="Gray"
X2="1" />
<WrapPanel>
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
<TextBlock Style="{StaticResource TextBlockLabel}">
Enable automatic adjustments of TLOD and OLOD to get the desired targeted frame rate (FPS).
</TextBlock>
</WrapPanel>
<WrapPanel Visibility="{Binding Path=AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
<appUserControl:DynamicLodPreference />
</WrapPanel>
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryDynamicLodSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
<WrapPanel>
<TextBlock
Padding="0,0,5,0"
Foreground="Red"
Style="{StaticResource TextBlockHeading}">
(Unsupported Feature)
</TextBlock>
<TextBlock Style="{StaticResource TextBlockHeading}">Dynamically adjust Terrain and Object Level of Details</TextBlock>
</WrapPanel>
<Line
Stretch="Fill"
Stroke="Gray"
X2="1" />
<WrapPanel>
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
<TextBlock Style="{StaticResource TextBlockLabel}">
Enable automatic adjustments of TLOD and OLOD to get the desired targeted frame rate (FPS).
</TextBlock>
</WrapPanel>
<WrapPanel Visibility="{Binding Path=AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
<appUserControl:DynamicLodPreference />
</WrapPanel>
</WrapPanel>
</WrapPanel>

View file

@ -1,7 +1,10 @@
using Microsoft.Extensions.DependencyInjection;
using MSFSPopoutPanelManager.MainApp.ViewModel;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Navigation;
namespace MSFSPopoutPanelManager.MainApp.AppUserControl
{
@ -22,5 +25,11 @@ namespace MSFSPopoutPanelManager.MainApp.AppUserControl
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">
<Window.Resources>
<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="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="White" />
<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" />
</Style>
</Window.Resources>

View file

@ -13,7 +13,7 @@ namespace MSFSPopoutPanelManager.MainApp.AppWindow
{
private readonly NumPadViewModel _viewModel;
public NumPad(Guid panelId)
public NumPad(Guid panelId, int initialWidth, int initialHeight)
{
InitializeComponent();
if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
@ -30,8 +30,19 @@ namespace MSFSPopoutPanelManager.MainApp.AppWindow
throw new ApplicationException("Unable to instantiate NumPad window");
_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;

View file

@ -41,18 +41,5 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
get => SharedStorage.ApplicationWindow;
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 RollBackCommand { get; private set; }
public string ApplicationVersion { get; private set; }
public bool IsRollBackCommandVisible { get; private set; }
@ -30,7 +28,6 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
HyperLinkCommand = new DelegateCommand<string>(OnHyperLinkActivated);
DeleteAppCacheCommand = new DelegateCommand(OnDeleteAppCache);
RollBackCommand = new DelegateCommand(OnRollBack);
#if DEBUG
var buildConfig = " (Debug)";
@ -41,8 +38,6 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
#endif
ApplicationVersion = $"{WindowProcessManager.GetApplicationVersion()}{buildConfig}";
IsRollBackCommandVisible = _helpOrchestrator.IsRollBackUpdateEnabled();
HasOrphanAppCache = _helpOrchestrator.HasOrphanAppCache();
}
@ -68,9 +63,6 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
case "Version Info":
_helpOrchestrator.OpenVersionInfo();
break;
case "Open Data Folder":
_helpOrchestrator.OpenDataFolder();
break;
case "Download VCC Library":
_helpOrchestrator.DownloadVccLibrary();
break;
@ -82,15 +74,5 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel
_helpOrchestrator.DeleteAppCache();
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 () =>
{
var numPad = new NumPad(panelConfig.Id);
var numPad = new NumPad(panelConfig.Id, panelConfig.Width, panelConfig.Height);
numPad.Show();
await Task.Run(() =>

View file

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

View file

@ -41,6 +41,25 @@ namespace MSFSPopoutPanelManager.Orchestration
Task.Run(() => _flightSimOrchestrator.StartSimConnectServer()); // Start the SimConnect server
_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()
@ -56,7 +75,7 @@ namespace MSFSPopoutPanelManager.Orchestration
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.Synchronous = true;
AutoUpdater.AppTitle = "MSFS Pop Out Panel Manager";

View file

@ -21,7 +21,7 @@ namespace MSFSPopoutPanelManager.Orchestration
ApplicationSetting = new ApplicationSetting();
AppSettingDataManager.WriteAppSetting(ApplicationSetting);
}
// Auto Save data
ApplicationSetting.PropertyChanged += (_, e) =>
{

View file

@ -1,8 +1,8 @@
using System;
using MSFSPopoutPanelManager.DomainModel.DataFile;
using MSFSPopoutPanelManager.DomainModel.DataFile;
using MSFSPopoutPanelManager.DomainModel.Setting;
using MSFSPopoutPanelManager.Shared;
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
@ -18,10 +18,30 @@ namespace MSFSPopoutPanelManager.Orchestration
{
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();
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
{
@ -33,24 +53,44 @@ namespace MSFSPopoutPanelManager.Orchestration
{
try
{
Debug.WriteLine("Saving application settings data file...");
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 });
CreateAppSettings(appSetting);
}
catch
{
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.SimConnectAgent;
using MSFSPopoutPanelManager.WindowsAgent;
using Newtonsoft.Json.Linq;
using System;
using System.Diagnostics;
using System.Dynamic;
using System.Runtime.InteropServices;
namespace MSFSPopoutPanelManager.Orchestration

View file

@ -39,11 +39,6 @@ namespace MSFSPopoutPanelManager.Orchestration
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()
{
var appLocal = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
@ -104,35 +99,5 @@ namespace MSFSPopoutPanelManager.Orchestration
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)");
_keyPressCaptureList = new List<string>();
_globalKeyboardHook.OnKeyboardPressed -= HandleGlobalKeyboardHookOnKeyboardPressed;
_globalKeyboardHook?.Dispose();
_globalKeyboardHook = null;
if (_globalKeyboardHook != null)
{
_globalKeyboardHook.OnKeyboardPressed -= HandleGlobalKeyboardHookOnKeyboardPressed;
_globalKeyboardHook?.Dispose();
_globalKeyboardHook = null;
}
}
private void HandleGlobalKeyboardHookOnKeyboardPressed(object sender, GlobalKeyboardHookEventArgs e)

View file

@ -209,7 +209,7 @@ namespace MSFSPopoutPanelManager.Orchestration
foreach (var panel in panels)
{
if (!panel.FloatingPanel.IsEnabled || panel.FullScreen)
if (!panel.FloatingPanel.IsEnabled)
return;
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; }
[IgnorePropertyChanged]
internal AppSettingData AppSettingDataRef { private get; set; }
public AppSettingData AppSettingDataRef { private get; set; }
public void AddProfile(string profileName)
{
@ -29,7 +29,7 @@ namespace MSFSPopoutPanelManager.Orchestration
Profiles.Add(newProfile);
SetActiveProfile(newProfile.Id);
ProfileDataManager.WriteProfiles(Profiles);
ProfileDataManager.WriteProfiles(Profiles, AppSettingDataRef.ApplicationSetting.GeneralSetting.UseApplicationDataPath);
AppSettingDataRef.ApplicationSetting.SystemSetting.LastUsedProfileId = newProfile.Id;
}
@ -64,7 +64,7 @@ namespace MSFSPopoutPanelManager.Orchestration
Profiles.Add(newProfile);
SetActiveProfile(newProfile.Id);
ProfileDataManager.WriteProfiles(Profiles);
ProfileDataManager.WriteProfiles(Profiles, AppSettingDataRef.ApplicationSetting.GeneralSetting.UseApplicationDataPath);
AppSettingDataRef.ApplicationSetting.SystemSetting.LastUsedProfileId = newProfile.Id;
}
@ -99,7 +99,7 @@ namespace MSFSPopoutPanelManager.Orchestration
ActiveProfile.AircraftBindings.Add(aircraft);
ProfileDataManager.WriteProfiles(Profiles);
ProfileDataManager.WriteProfiles(Profiles, AppSettingDataRef.ApplicationSetting.GeneralSetting.UseApplicationDataPath);
RefreshProfile();
}
@ -110,13 +110,13 @@ namespace MSFSPopoutPanelManager.Orchestration
ActiveProfile.AircraftBindings.Remove(aircraft);
ProfileDataManager.WriteProfiles(Profiles);
ProfileDataManager.WriteProfiles(Profiles, AppSettingDataRef.ApplicationSetting.GeneralSetting.UseApplicationDataPath);
RefreshProfile();
}
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());
// Detect profiles collection changes
@ -135,7 +135,7 @@ namespace MSFSPopoutPanelManager.Orchestration
public void WriteProfiles()
{
Debug.WriteLine("Saving Data ... ");
ProfileDataManager.WriteProfiles(Profiles);
ProfileDataManager.WriteProfiles(Profiles, AppSettingDataRef.ApplicationSetting.GeneralSetting.UseApplicationDataPath);
}
public void SetActiveProfile(Guid id)

View file

@ -13,13 +13,13 @@ namespace MSFSPopoutPanelManager.Orchestration
{
private const string USER_PROFILE_DATA_FILENAME = "userprofiledata.json";
public static IList<UserProfile> ReadProfiles()
public static IList<UserProfile> ReadProfiles(bool isRoamingPath)
{
try
{
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();
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)
{
@ -40,22 +40,44 @@ namespace MSFSPopoutPanelManager.Orchestration
try
{
var dataFilePath = FileIo.GetUserDataFilePath();
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 });
CreateProfiles(profiles, isRoamingPath);
}
catch
{
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

@ -170,4 +170,6 @@ Thank you for your super kind support of this app!
[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.
* 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.
* Fixed various smaller bugs.

View file

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

View file

@ -11,7 +11,7 @@ namespace MSFSPopoutPanelManager.Shared
public class FileLogger
{
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod()?.DeclaringType);
static FileLogger()
{
// Setup log4Net
@ -24,18 +24,12 @@ namespace MSFSPopoutPanelManager.Shared
if (LogManager.GetRepository(Assembly.GetEntryAssembly()).GetAppenders().First() is not RollingFileAppender errorLogAppender)
return;
errorLogAppender.File = FileIo.GetErrorLogFilePath();
errorLogAppender.File = FileIo.GetErrorLogFilePath(UseApplicationDataPath);
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)
{
switch (messageType)
@ -43,12 +37,12 @@ namespace MSFSPopoutPanelManager.Shared
case StatusMessageType.Error:
Log.Error(message);
break;
//case StatusMessageType.Info:
// Log.Info(message);
// break;
//case StatusMessageType.Debug:
// Log.Debug(message);
// break;
//case StatusMessageType.Info:
// Log.Info(message);
// break;
//case StatusMessageType.Debug:
// Log.Debug(message);
// break;
}
}
@ -56,5 +50,10 @@ namespace MSFSPopoutPanelManager.Shared
{
Log.Error(message, exception);
}
public static void CloseFileLogger()
{
LogManager.ShutdownRepository();
}
}
}

View file

@ -1,6 +1,22 @@
# Version History
<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
* 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.