Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 28, 2025

Changes proposed in this pull request

  • Migrate profile file serialization from XML to JSON format, matching the SettingsManager pattern from PR Migrate settings storage from XML to JSON with automatic migration #3282
  • Add automatic migration logic that converts legacy XML files to JSON on first load (both encrypted and unencrypted)
  • Implement helper methods: GetJsonProfilePath() for path construction and IsXmlContent() for efficient format detection (checks first 200 bytes)
  • Add comprehensive null safety and error handling with logging for all file operations
  • Fix ProfileFiles collection update order during migration to prevent UI issues (follows existing pattern: Add new → Remove old)

Related issue(s)

Copilot generated summary

Provide a Copilot generated summary of the changes in this pull request.

Copilot summary

This PR migrates NETworkManager profile files from XML to JSON format. The implementation:

Core Changes:

  • Changed default extension from .xml to .json
  • Added JSON serialization using System.Text.Json with indented formatting, case-insensitive deserialization, and enum converters
  • Legacy XML methods marked [Obsolete] for backward compatibility during migration

Migration Logic:

  • Unencrypted: Detects .xml extension → deserialize XML → serialize JSON → delete old file
  • Encrypted: Decrypt → detect format via content inspection → convert if XML → re-encrypt → delete old file
  • Profile data (names, groups, settings) fully preserved
  • Failed file deletions logged but don't halt migration

Key Methods:

// Path construction helper
private static string GetJsonProfilePath(string originalPath, bool encrypted)
{
    var basePath = Path.ChangeExtension(originalPath, null);
    return encrypted 
        ? $"{basePath}{ProfileFileExtension}{ProfileFileExtensionEncrypted}"
        : $"{basePath}{ProfileFileExtension}";
}

// Efficient XML detection (first 200 bytes only)
private static bool IsXmlContent(byte[] data)
{
    var bytesToCheck = Math.Min(XmlDetectionBufferSize, data.Length);
    var text = Encoding.UTF8.GetString(data, 0, bytesToCheck).TrimStart();
    return text.StartsWith("<?xml") || text.StartsWith("<ArrayOfGroupInfoSerializable");
}

Collection Update Pattern:
The ProfileFiles collection update order follows the existing pattern used throughout the class (RenameProfileFile, EnableEncryption, etc.):

  1. Add new profile to collection
  2. Update local reference
  3. Delete old file
  4. Remove old profile from collection

This prevents UI update issues during migration.

Safety & Quality:

  • All deserialization paths validate null results
  • File operations wrapped in try-catch with logging
  • Null-safe Profiles collection access: groupSerializable.Profiles ?? new List<ProfileInfoSerializable>()
  • Performance optimized for large files
  • Proper collection sequencing prevents UI glitches

To-Do

Contributing

By submitting this pull request, I confirm the following:

Original prompt

Migrate the profile files in Source/NETworkManager.Profiles/ProfileManager.cs from xml to json similar to what we have done with the settingsmanager already in #3282

Be careful with the profile file encryption and that the profiles (list of names) load correct. The migration should happen when the file is loading (e.g. after unencrpytion, if encrypted)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI changed the title [WIP] Migrate profile files from XML to JSON format Migrate profile files from XML to JSON format Dec 28, 2025
Copilot AI requested a review from BornToBeRoot December 28, 2025 14:45
@BornToBeRoot
Copy link
Owner

@copilot there is an issue when loading a file and it will be removed/re-added (with a different profilefileinfo). The collection will change and the UI is wrongly updated.

Can you check the existing logic that is used when a profile is removed / readded.

This is part with the issue:

       // Update ProfileFiles collection
       ProfileFiles.Remove(profileFileInfo);
       ProfileFiles.Add(newProfileFileInfo);

And this might be a possible fix that is already working in some other part of this class (check and validate if this is true)


        // Add the new profile
        ProfileFiles.Add(newProfileFileInfo);

        // Switch profile, if it was previously loaded
        if (switchProfile)
        {
            Switch(newProfileFileInfo, false);
            LoadedProfileFileChanged(LoadedProfileFile, true);
        }

        // Remove the old profile file
        File.Delete(profileFileInfo.Path);
        ProfileFiles.Remove(profileFileInfo);

Copy link
Contributor Author

Copilot AI commented Jan 2, 2026

@copilot there is an issue when loading a file and it will be removed/re-added (with a different profilefileinfo). The collection will change and the UI is wrongly updated.

Can you check the existi...

Fixed in commit 37869e5. The ProfileFiles collection update order now follows the existing pattern used in RenameProfileFile, EnableEncryption, ChangeMasterPassword, and DisableEncryption methods:

  1. Add new profile to collection
  2. Update local reference
  3. Delete old file
  4. Remove old profile from collection

This prevents the UI from being incorrectly updated during migration.

@BornToBeRoot
Copy link
Owner

BornToBeRoot commented Jan 3, 2026

@copilot Revert the last commit and use the existing logic, because this implements a ui change already...

@BornToBeRoot
Copy link
Owner

Close because of #3299

@BornToBeRoot BornToBeRoot deleted the copilot/migrate-profiles-to-json branch January 5, 2026 01:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants