Keep the files in N1MM's folders

The folders under the user's own directory are N1MM's now, with N1MM's names,
read out of N1MMLibrary.dll: Databases, SupportFiles, UserDefinedContests,
FunctionKeyMessages, CallHistoryFiles, ExportFiles, GoalFiles, LettersFiles,
QsoRecording, SkinsAndLayouts, SystemFiles, TransactionLogFiles, Diagnostics
and Wav. A station that runs both programs keeps its files in one shape.

An operator's recordings go in Wav/<his callsign>, which is where N1MM plays
them from, and the folder is made when he takes the radio. Cabrillo and ADIF
start in ExportFiles, call history files in CallHistoryFiles, and the .mc
function key files in FunctionKeyMessages.

N1MM's three *DDL folders and its Piper folders are left out: they hold the
migrations for N1MM's own admin databases and the program it speaks with.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoGtneMQaz4M9w7Kk49AVD
This commit is contained in:
2026-08-31 22:59:45 +00:00
co-authored by Claude Opus 5
parent 654adda080
commit 2c51b5293a
7 changed files with 204 additions and 8 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ public sealed partial class EntryWindow
string stored = mode == ModeCategory.Phone
? session.Settings.PhoneMessageFile
: session.Settings.CwMessageFile;
if (await new MessagesDialog(mode, stored).ShowDialog<string?>(this) is not { } edited)
if (await new MessagesDialog(mode, stored, folder: session.Paths.FunctionKeyMessages).ShowDialog<string?>(this) is not { } edited)
{
return;
}
+4 -1
View File
@@ -102,6 +102,7 @@ public sealed partial class EntryWindow
{
Title = "Export Cabrillo",
SuggestedFileName = $"{session.Settings.Station.Callsign}.log",
SuggestedStartLocation = await Folder(session.Paths.ExportFiles),
});
if (file?.TryGetLocalPath() is not { } path)
{
@@ -142,6 +143,7 @@ public sealed partial class EntryWindow
{
Title = "Export ADIF",
SuggestedFileName = $"{session.Settings.Station.Callsign}.adi",
SuggestedStartLocation = await Folder(session.Paths.ExportFiles),
});
if (file?.TryGetLocalPath() is not { } path)
{
@@ -162,6 +164,7 @@ public sealed partial class EntryWindow
{
Title = "Import ADIF",
AllowMultiple = false,
SuggestedStartLocation = await Folder(session.Paths.ExportFiles),
});
if (files.FirstOrDefault()?.TryGetLocalPath() is not { } path)
{
@@ -573,7 +576,7 @@ public sealed partial class EntryWindow
{
Title = "Call history file",
AllowMultiple = false,
SuggestedStartLocation = await Folder(session.Paths.SupportFiles),
SuggestedStartLocation = await Folder(session.Paths.CallHistoryFiles),
});
if (files.FirstOrDefault()?.TryGetLocalPath() is not { } path)
{
@@ -41,6 +41,7 @@ public sealed partial class EntryWindow
? known with { WavPath = wanted.WavPath }
// a new operator starts with the windows and colours on the screen
: wanted with { Theme = settings.Theme, Windows = Layout() };
stored = stored with { WavPath = WavFolder(stored) };
session.Save(settings with
{
Operators = [.. settings.Operators.Where(o => !Is(o, stored.Callsign)), stored],
@@ -62,6 +63,28 @@ public sealed partial class EntryWindow
Status($"operator {stored.Callsign}");
}
/// The operator's recordings folder: the one he named, or `Wav/<callsign>`
/// beside the rest of the files, which is where N1MM keeps them. The folder
/// is made, so there is somewhere to put the files rather than a path that
/// is not there.
private string WavFolder(StoredOperator stored)
{
string folder = stored.WavPath.Trim().Length > 0
? stored.WavPath.Trim()
: session.Paths.WavFor(stored.Callsign);
try
{
Directory.CreateDirectory(folder);
}
catch (Exception failure) when (failure is IOException or UnauthorizedAccessException)
{
// a folder on a drive that is not there is still worth keeping: it
// is the operator's own setting, and he is the one who fixes it
Status($"{folder} could not be made: {failure.Message}");
}
return folder;
}
/// Puts a window where this operator last had it. Windows are opened one at
/// a time, so each one is placed as it appears rather than all at once.
private void Place(Window window, StoredOperator? stored = null)