Skip to content

Commit

Permalink
Saves and restores main window size and position
Browse files Browse the repository at this point in the history
  • Loading branch information
tareqimbasher committed Nov 27, 2023
1 parent a2e96b6 commit a548f37
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 8 deletions.
1 change: 1 addition & 0 deletions src/Apps/NetPad.Apps.App/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddTransient<IAssemblyLoader, UnloadableAssemblyLoader>();
services.AddTransient<ILogoService, LogoService>();
services.AddSingleton<IAppStatusMessagePublisher, AppStatusMessagePublisher>();
services.AddSingleton<IKeyValueDataStore, FileSystemKeyValueDataStore>();

// Scripts
services.AddTransient<IScriptRepository, FileSystemScriptRepository>();
Expand Down
11 changes: 11 additions & 0 deletions src/Core/NetPad.Domain/Data/IKeyValueDataStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace NetPad.Data;

/// <summary>
/// Represents a key-value data store.
/// </summary>
public interface IKeyValueDataStore
{
TValue? Get<TValue>(string key) where TValue : class;
void Set<TValue>(string key, TValue value);
bool Contains(string key);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using ElectronNET.API;
using ElectronNET.API.Entities;
using Microsoft.Extensions.Logging;
using NetPad.Configuration;
using NetPad.Data;
using NetPad.Scripts;
using NetPad.UiInterop;

Expand All @@ -9,12 +11,14 @@ namespace NetPad.Electron.UiInterop;
public class ElectronWindowService : IUiWindowService
{
private readonly WindowManager _windowManager;
private readonly IKeyValueDataStore _keyValueDataStore;
private readonly Settings _settings;
private readonly ILogger<ElectronWindowService> _logger;

public ElectronWindowService(WindowManager windowManager, Settings settings, ILogger<ElectronWindowService> logger)
public ElectronWindowService(WindowManager windowManager, IKeyValueDataStore keyValueDataStore, Settings settings, ILogger<ElectronWindowService> logger)
{
_windowManager = windowManager;
_keyValueDataStore = keyValueDataStore;
_settings = settings;
_logger = logger;
}
Expand All @@ -25,21 +29,46 @@ public async Task OpenMainWindowAsync()
{
bool useNativeDecorations = _settings.Appearance.Titlebar.Type == TitlebarType.Native;

var display = await PrimaryDisplay();
var window = await _windowManager.CreateWindowAsync("main", true, new BrowserWindowOptions
{
Show = false,
Height = display.Bounds.Height * 2 / 3,
Width = display.Bounds.Width * 2 / 3,
X = display.Bounds.X,
Y = display.Bounds.Y,
Frame = useNativeDecorations,
AutoHideMenuBar = _settings.Appearance.Titlebar.MainMenuVisibility == MainMenuVisibility.AutoHidden,
Fullscreenable = true,
});

window.Show();
window.Maximize();
await RestoreMainWindowPositionAsync(window);
}

private async Task RestoreMainWindowPositionAsync(BrowserWindow window)
{
try
{
var savedBounds = _keyValueDataStore.Get<Rectangle>("main-window.bounds");
if (savedBounds != null)
{
window.SetBounds(savedBounds);
window.Show();
}
else
{
var display = await PrimaryDisplay();
window.SetBounds(display.Bounds);
window.Show();
window.Maximize();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while restoring main window size and position");
window.Show();
window.Maximize();
}

window.OnClose += async () =>
{
_keyValueDataStore.Set("main-window.bounds", await window.GetBoundsAsync());
};
}

public async Task OpenSettingsWindowAsync(string? tab = null)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NetPad.Common;
using NetPad.Configuration;
using NetPad.Data;
using NetPad.IO;

namespace NetPad;

public class FileSystemKeyValueDataStore : IKeyValueDataStore
{
private static readonly FilePath _storeFilePath = AppDataProvider.AppDataDirectoryPath.CombineFilePath("key-values.txt");
private static readonly object _fileLock = new();

public TValue? Get<TValue>(string key) where TValue : class
{
lock (_fileLock)
{
if (!_storeFilePath.Exists())
{
return null;
}

using var reader = File.OpenText(_storeFilePath.Path);
while (reader.ReadLine() is { } line)
{
if (line.Length == 0 || !line.StartsWith(key))
{
continue;
}

var parts = line.Split('=', 2);
if (parts.Length < 2)
{
continue;
}

return JsonSerializer.Deserialize<TValue>(parts[1].Trim());
}
}

return null;
}

public void Set<TValue>(string key, TValue value)
{
lock (_fileLock)
{
var lines = _storeFilePath.Exists()
? File.ReadAllLines(_storeFilePath.Path).ToList()
: new List<string>();

var iLine = lines.FindIndex(l => l.StartsWith(key));

if (iLine >= 0)
{
lines[iLine] = $"{key}={JsonSerializer.Serialize(value)}";
}
else
{
lines.Add($"{key}={JsonSerializer.Serialize(value)}");
}

File.WriteAllLines(_storeFilePath.Path, lines);
}
}

public bool Contains(string key)
{
lock (_fileLock)
{
if (!_storeFilePath.Exists())
{
return false;
}

using var reader = File.OpenText(_storeFilePath.Path);
while (reader.ReadLine() is { } line)
{
if (line.Length == 0 || !line.StartsWith(key))
{
continue;
}

return true;
}
}

return false;
}
}

0 comments on commit a548f37

Please sign in to comment.