Repository: PixiEditor/PixiEditor
File: src/PixiEditor.ChangeableDocument/Changes/Structure/ApplyMask_Change.cs (C#)

Code before:
﻿using PixiEditor.ChangeableDocument.Changes.Drawing;
using PixiEditor.DrawingApi.Core.Numerics;
using PixiEditor.DrawingApi.Core.Surface;
using PixiEditor.DrawingApi.Core.Surface.PaintImpl;

namespace PixiEditor.ChangeableDocument.Changes.Structure;

internal sealed class ApplyMask_Change : Change
{
    private Guid structureMemberGuid;
    private Layer? layer;
    
    private CommittedChunkStorage? savedChunks;

    [GenerateMakeChangeAction]
    public ApplyMask_Change(Guid structureMemberGuid)
    {
        this.structureMemberGuid = structureMemberGuid;
    }
        
    public override bool InitializeAndValidate(Document target)
    {
        var member = target.FindMember(structureMemberGuid);
        bool isValid = member is not (null or Folder) && member.Mask is not null;
        if (isValid)
        {
            layer = member as Layer;
        }
        
        return isValid;
    }

    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
    {
        layer!.LayerImage.EnqueueApplyMask(layer.Mask!);
        ignoreInUndo = false;

Review comment (suggestion):
Storing a reference to a layer inside a change is a very bad idea, you must store a guid instead
from PixiEditorPrototype readme:
"Note that changes must not store any references to the Document, Layers, ChunkyImages, and other IChangeables. If any data needs to be stored for revert to work, it must be copied. If you need to refer to some layer, store it's GUID. Consider a situation where you create a layer, draw on it, undo twice, and redo twice. When you undo the layer gets deleted, and then recreated on redo. If the drawing change were to store a reference to the layer we'd get an exception when trying to redo it. It is possible to carefully implement the new layer operation in a way that preserves the reference, but it's a lot easier not to store references at all."

Code after:
﻿using PixiEditor.ChangeableDocument.Changes.Drawing;
using PixiEditor.DrawingApi.Core.Numerics;
using PixiEditor.DrawingApi.Core.Surface;
using PixiEditor.DrawingApi.Core.Surface.PaintImpl;

namespace PixiEditor.ChangeableDocument.Changes.Structure;

internal sealed class ApplyMask_Change : Change
{
    private Guid structureMemberGuid;

    private CommittedChunkStorage? savedChunks;

    [GenerateMakeChangeAction]
    public ApplyMask_Change(Guid structureMemberGuid)
    {
        this.structureMemberGuid = structureMemberGuid;
    }
        
    public override bool InitializeAndValidate(Document target)
    {
        var member = target.FindMember(structureMemberGuid);
        bool isValid = member is not (null or Folder) && member.Mask is not null;

        return isValid;
    }

    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
    {
        var layer = (Layer)target.FindMember(structureMemberGuid)!;
        layer!.LayerImage.EnqueueApplyMask(layer.Mask!);
        ignoreInUndo = false;
        var layerInfo = new LayerImageChunks_ChangeInfo(structureMemberGuid, layer.LayerImage.FindAffectedChunks());
        savedChunks = new CommittedChunkStorage(layer.LayerImage, layerInfo.Chunks);
        
        layer.LayerImage.CommitChanges();