Added Git Export Feature
- Added import algorithm - Added FromJsonX() methods to data models - Added possibility to work with temp. database file - Added export processor to handle export process & triggers - Added something changed event e.g. as export trigger - Added possibility to import a JSON export - Updated Git icon
This commit is contained in:
20 files changed
+411
-62
No files matched your search
@@ -4,12 +4,19 @@ namespace UI_WinForms;
|
||||
|
||||
internal static class AppEvents
|
||||
{
|
||||
static AppEvents()
|
||||
{
|
||||
AppEvents.AddSomethingHandlers();
|
||||
}
|
||||
|
||||
internal static void ResetAllSubscriptions()
|
||||
{
|
||||
WhenSettingsChanged = null;
|
||||
WhenSectionChanged = null;
|
||||
WhenTextElementChanged = null;
|
||||
WhenTranslationChanged = null;
|
||||
|
||||
AppEvents.AddSomethingHandlers();
|
||||
}
|
||||
|
||||
#region Event: Settings changed
|
||||
@@ -49,4 +56,20 @@ internal static class AppEvents
|
||||
internal static void TranslationChanged(Translation? translation) => WhenTranslationChanged?.Invoke(null, translation);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event: Something was changed
|
||||
|
||||
internal static event EventHandler? WhenSomethingChanged;
|
||||
|
||||
internal static void SomethingChanged() => WhenSomethingChanged?.Invoke(null, EventArgs.Empty);
|
||||
|
||||
private static void AddSomethingHandlers()
|
||||
{
|
||||
// Raise the something event when any of the other change-events are raised:
|
||||
WhenSectionChanged += (sender, args) => WhenSomethingChanged?.Invoke(sender, EventArgs.Empty);
|
||||
WhenTextElementChanged += (sender, args) => WhenSomethingChanged?.Invoke(sender, EventArgs.Empty);
|
||||
WhenTranslationChanged += (sender, args) => WhenSomethingChanged?.Invoke(sender, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -62,6 +62,7 @@ public partial class LoaderStart : UserControl
|
||||
|
||||
#endregion
|
||||
|
||||
// Opens the recent projects dropdown menu.
|
||||
private void buttonOpen_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(this.DesignMode)
|
||||
@@ -84,9 +85,19 @@ public partial class LoaderStart : UserControl
|
||||
// Split the file's path into each folder's name:
|
||||
var folderNames = fileInfo.DirectoryName!.Split(Path.DirectorySeparatorChar);
|
||||
|
||||
// Render this entry:
|
||||
var item = this.contextMenuRecentProjects.Items.Add($"{folderNames.Last()}: {fileInfo.Name}", Resources.Icons.icons8_document_512, (innerSender, args) => this.OpenRecentProject(innerSender));
|
||||
item.Tag = recentProject;
|
||||
// Distinguish between I18N Commander projects and JSON imports:
|
||||
if (fileInfo.Extension == ".i18nc")
|
||||
{
|
||||
// Render this entry:
|
||||
var item = this.contextMenuRecentProjects.Items.Add($"{folderNames.Last()}: {fileInfo.Name}", Resources.Icons.icons8_document_512, (innerSender, args) => this.OpenRecentProject(innerSender, LoaderAction.LOAD_PROJECT));
|
||||
item.Tag = recentProject;
|
||||
}
|
||||
else if (fileInfo.Extension == ".json")
|
||||
{
|
||||
// Render this entry:
|
||||
var item = this.contextMenuRecentProjects.Items.Add($"{folderNames.Last()}: {fileInfo.Name}", Resources.Icons.icons8_git, (innerSender, args) => this.OpenRecentProject(innerSender, LoaderAction.IMPORT_JSON));
|
||||
item.Tag = recentProject;
|
||||
}
|
||||
}
|
||||
|
||||
var button = (sender as Button)!;
|
||||
@@ -125,7 +136,7 @@ public partial class LoaderStart : UserControl
|
||||
File.Delete(destinationFilePath);
|
||||
|
||||
LoaderStart.UpdateRecentProjectsWithPruning(destinationFilePath);
|
||||
this.OpenProject(destinationFilePath);
|
||||
this.OpenProject(LoaderAction.CREATE_NEW_PROJECT, destinationFilePath);
|
||||
}
|
||||
|
||||
private void BrowseForProject()
|
||||
@@ -137,10 +148,12 @@ public partial class LoaderStart : UserControl
|
||||
CheckFileExists = true,
|
||||
DereferenceLinks = true,
|
||||
DefaultExt = ".i18nc",
|
||||
Filter = "I18N Commander Files (*.i18nc)|*.i18nc",
|
||||
|
||||
// I18N Commander files (*.i18nc) or JSON files (*.json):
|
||||
Filter = "I18N Commander Files (*.i18nc)|*.i18nc|JSON Files (*.json)|*.json",
|
||||
Multiselect = false,
|
||||
RestoreDirectory = true,
|
||||
Title = "Open an I18N Commander file",
|
||||
Title = "Open an I18N Commander file or Import a JSON file",
|
||||
};
|
||||
var dialogResult = openDialog.ShowDialog(this);
|
||||
if (dialogResult != DialogResult.OK)
|
||||
@@ -148,23 +161,28 @@ public partial class LoaderStart : UserControl
|
||||
|
||||
var projectFilePath = openDialog.FileName;
|
||||
LoaderStart.UpdateRecentProjectsWithPruning(projectFilePath);
|
||||
this.OpenProject(projectFilePath);
|
||||
|
||||
// Check, if the user chose an I18N Commander file or a JSON file:
|
||||
if (projectFilePath.ToLowerInvariant().EndsWith(".i18nc", StringComparison.InvariantCulture))
|
||||
this.OpenProject(LoaderAction.LOAD_PROJECT, projectFilePath);
|
||||
else if (projectFilePath.ToLowerInvariant().EndsWith(".json", StringComparison.InvariantCulture))
|
||||
this.OpenProject(LoaderAction.IMPORT_JSON, projectFilePath);
|
||||
}
|
||||
|
||||
private void OpenRecentProject(object? sender)
|
||||
private void OpenRecentProject(object? sender, LoaderAction action)
|
||||
{
|
||||
if (sender is not ToolStripItem item)
|
||||
return;
|
||||
|
||||
var path = (item.Tag as string)!;
|
||||
LoaderStart.UpdateRecentProjectsWithPruning(path);
|
||||
this.OpenProject(path);
|
||||
this.OpenProject(action, path);
|
||||
}
|
||||
|
||||
private void OpenProject(string path)
|
||||
private void OpenProject(LoaderAction action, string path)
|
||||
{
|
||||
// Hint: the project file might or might not exist (new project vs. recent project)
|
||||
this.LoadProject?.Invoke(this, path);
|
||||
this.LoadProject?.Invoke(this, new LoaderResult(action, path));
|
||||
}
|
||||
|
||||
private void contextMenuRecentProjects_Closing(object sender, ToolStripDropDownClosingEventArgs e)
|
||||
@@ -173,5 +191,16 @@ public partial class LoaderStart : UserControl
|
||||
}
|
||||
|
||||
[Category("Settings"), Description("When the user chooses a project to load.")]
|
||||
public event EventHandler<string>? LoadProject;
|
||||
public event EventHandler<LoaderResult>? LoadProject;
|
||||
|
||||
public readonly record struct LoaderResult(LoaderAction Action, string DataFile);
|
||||
|
||||
public enum LoaderAction
|
||||
{
|
||||
NONE,
|
||||
|
||||
LOAD_PROJECT,
|
||||
CREATE_NEW_PROJECT,
|
||||
IMPORT_JSON,
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace UI_WinForms.Components;
|
||||
using Processor;
|
||||
|
||||
namespace UI_WinForms.Components;
|
||||
|
||||
public partial class Main : UserControl
|
||||
{
|
||||
@@ -6,6 +8,9 @@ public partial class Main : UserControl
|
||||
{
|
||||
this.InitializeComponent();
|
||||
Program.RestartMainApp = false;
|
||||
|
||||
// Register the something changed event to trigger the export:
|
||||
AppEvents.WhenSomethingChanged += async (_, _) => await ExportProcessor.TriggerExport();
|
||||
}
|
||||
|
||||
private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
|
||||
|
||||
@@ -690,7 +690,7 @@ public sealed partial class Setting : UserControl
|
||||
{
|
||||
var currentSetting = await AppSettings.GetAutoExportEnabled();
|
||||
var settingData = new SettingUIData(
|
||||
Icon: Icons.icons8_git_svg,
|
||||
Icon: Icons.icons8_git,
|
||||
SettingName: () => "Git (JSON) Auto-Export: Enabled",
|
||||
ChangeNeedsRestart: true,
|
||||
SettingExplanation: () => "When enabled, all changes are automatically exported into a Git repository as JSON file.",
|
||||
@@ -700,9 +700,13 @@ public sealed partial class Setting : UserControl
|
||||
// Set up an checkbox:
|
||||
var checkbox = new CheckBox();
|
||||
checkbox.Checked = currentSetting;
|
||||
checkbox.CheckedChanged += async (sender, args) => await AppSettings.SetAutoExportEnabled(checkbox.Checked);
|
||||
checkbox.CheckedChanged += (sender, args) => changeTrigger();
|
||||
checkbox.Text = "Enable Git (JSON) Auto-Export";
|
||||
checkbox.CheckedChanged += async (sender, args) =>
|
||||
{
|
||||
await AppSettings.SetAutoExportEnabled(checkbox.Checked);
|
||||
await ExportProcessor.TriggerExport();
|
||||
changeTrigger();
|
||||
};
|
||||
checkbox.Text = "Enable Auto-Export";
|
||||
|
||||
// Apply the desired layout:
|
||||
checkbox.Dock = DockStyle.Fill;
|
||||
@@ -717,7 +721,7 @@ public sealed partial class Setting : UserControl
|
||||
{
|
||||
var currentSetting = await AppSettings.GetAutoExportDestinationPath();
|
||||
var settingData = new SettingUIData(
|
||||
Icon: Icons.icons8_git_svg,
|
||||
Icon: Icons.icons8_git,
|
||||
SettingName: () => "Git (JSON) Auto-Export: Destination Path",
|
||||
ChangeNeedsRestart: true,
|
||||
SettingExplanation: () => "The destination path for the Git repository. You might use environment variables like %USERPROFILE%.",
|
||||
@@ -775,7 +779,7 @@ public sealed partial class Setting : UserControl
|
||||
{
|
||||
var currentSetting = await AppSettings.GetAutoExportFilename();
|
||||
var settingData = new SettingUIData(
|
||||
Icon: Icons.icons8_git_svg,
|
||||
Icon: Icons.icons8_git,
|
||||
SettingName: () => "Git (JSON) Auto-Export: Filename",
|
||||
ChangeNeedsRestart: true,
|
||||
SettingExplanation: () => "The filename used for the Git export. You might use environment variables like %USERPROFILE%.",
|
||||
@@ -800,7 +804,7 @@ public sealed partial class Setting : UserControl
|
||||
{
|
||||
var currentSetting = await AppSettings.GetAutoExportSensitiveData();
|
||||
var settingData = new SettingUIData(
|
||||
Icon: Icons.icons8_git_svg,
|
||||
Icon: Icons.icons8_git,
|
||||
SettingName: () => "Git (JSON) Auto-Export: Export Sensitive Data",
|
||||
ChangeNeedsRestart: true,
|
||||
SettingExplanation: () => "When enabled, sensitive data like API tokens are exported into the Git repository. This is not recommended!",
|
||||
|
||||
+4
-2
@@ -1,4 +1,6 @@
|
||||
namespace UI_WinForms
|
||||
using UI_WinForms.Components;
|
||||
|
||||
namespace UI_WinForms
|
||||
{
|
||||
partial class Loader
|
||||
{
|
||||
@@ -57,7 +59,7 @@
|
||||
this.loaderStart.Name = "loaderStart";
|
||||
this.loaderStart.Size = new System.Drawing.Size(794, 444);
|
||||
this.loaderStart.TabIndex = 0;
|
||||
this.loaderStart.LoadProject += new System.EventHandler<string>(this.loaderStart_LoadProject);
|
||||
this.loaderStart.LoadProject += new System.EventHandler<LoaderStart.LoaderResult>(this.loaderStart_LoadProject);
|
||||
//
|
||||
// Loader
|
||||
//
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
namespace UI_WinForms;
|
||||
using UI_WinForms.Components;
|
||||
|
||||
namespace UI_WinForms;
|
||||
|
||||
public partial class Loader : Form
|
||||
{
|
||||
public string DataFile { get; set; } = string.Empty;
|
||||
public LoaderStart.LoaderResult Result { get; private set; }
|
||||
|
||||
public Loader()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void loaderStart_LoadProject(object sender, string projectFilePath)
|
||||
private void loaderStart_LoadProject(object sender, LoaderStart.LoaderResult result)
|
||||
{
|
||||
if(this.DesignMode)
|
||||
return;
|
||||
|
||||
this.DataFile = projectFilePath;
|
||||
this.Result = result;
|
||||
this.DialogResult = DialogResult.OK;
|
||||
this.Close();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
using System.Text.Json;
|
||||
using DataModel;
|
||||
using DataModel.Database.Common;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Processor;
|
||||
|
||||
using static UI_WinForms.Components.LoaderStart.LoaderAction;
|
||||
|
||||
namespace UI_WinForms;
|
||||
|
||||
internal static class Program
|
||||
@@ -25,7 +28,7 @@ internal static class Program
|
||||
// Check, if the user closes the loader screen:
|
||||
if (loader.DialogResult != DialogResult.OK)
|
||||
return;
|
||||
|
||||
|
||||
//
|
||||
// Create the DI system
|
||||
//
|
||||
@@ -36,10 +39,25 @@ internal static class Program
|
||||
//
|
||||
builder.ConfigureServices((hostContext, serviceCollection) =>
|
||||
{
|
||||
// The database:
|
||||
serviceCollection.AddDatabase(loader.DataFile, true);
|
||||
if(loader.Result.Action is LOAD_PROJECT or CREATE_NEW_PROJECT)
|
||||
serviceCollection.AddDatabase(loader.Result.DataFile, true);
|
||||
else if(loader.Result.Action is IMPORT_JSON)
|
||||
{
|
||||
try
|
||||
{
|
||||
serviceCollection.ImportDataAndAddDatabase(loader.Result.DataFile).ConfigureAwait(false);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
MessageBox.Show($"The JSON file '{loader.Result.DataFile}' is invalid and cannot be imported.", "Invalid JSON file", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
Environment.Exit(100);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Tear down the setup:
|
||||
using var setupMaintenance = Setup.Maintenance;
|
||||
|
||||
// Get the host out of the DI system:
|
||||
var host = builder.Build();
|
||||
|
||||
|
||||
+2
-2
@@ -213,9 +213,9 @@ namespace UI_WinForms.Resources {
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap icons8_git_svg {
|
||||
internal static System.Drawing.Bitmap icons8_git {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("icons8_git_svg", resourceCulture);
|
||||
object obj = ResourceManager.GetObject("icons8_git", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,8 +163,8 @@
|
||||
<data name="icons8_folder_tree_512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>icons8-folder-tree-512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="icons8_git_svg" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>icons8-git.svg.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="icons8_git" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>icons8-git.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="icons8_increase_512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>icons8-increase-512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
Reference in new issue
Block a user