@@ -599,10 +599,35 @@ local function onRightClick_KEYBINDINGS(editframe, container, group, unique)
599599 )
600600end
601601
602+ -- ponytail: true if a seq is corrupt/unusable — decode-broken (in
603+ -- GSE.CorruptSequences) or loaded-but-structurally-broken. Matches what the tree
604+ -- flags red; used to give a Delete-only right-click menu (the normal items call
605+ -- FindSequence, which DecodeMessages the broken data and errors).
606+ local function isBrokenSeq (classid , name )
607+ local cid = tonumber (classid )
608+ if not cid or GSE .isEmpty (name ) then return false end
609+ for _ , c in ipairs (GSE .CorruptSequences or {}) do
610+ if tonumber (c .classid ) == cid and c .name == name then return true end
611+ end
612+ local libSeq = GSE .Library [cid ] and GSE .Library [cid ][name ]
613+ return libSeq ~= nil and GSE .IsSequenceStructurallyBroken (libSeq )
614+ end
615+
602616local function onRightClick_Sequences (editframe , container , group , unique , classid , sequencename )
603617 MenuUtil .CreateContextMenu (
604618 editframe .frame ,
605619 function (ownerRegion , rootDescription )
620+ -- ponytail: a flagged corrupt/broken seq can't be edited/duplicated/
621+ -- exported (those call FindSequence -> DecodeMessage on broken data and
622+ -- crash). Offer Delete only.
623+ if not GSE .isEmpty (sequencename ) and isBrokenSeq (classid , sequencename ) then
624+ rootDescription :CreateTitle (L [" Corrupt Sequence" ])
625+ rootDescription :CreateButton (L [" Delete" ], function ()
626+ editframe .GUIDeleteSequence (classid , sequencename )
627+ if editframe .ManageTree then editframe .ManageTree () end
628+ end )
629+ return
630+ end
606631 rootDescription :CreateTitle (L [" Sequence Editor" ])
607632 rootDescription :CreateButton (L [" New" ], function ()
608633 if editframe .loaded then
@@ -1139,6 +1164,14 @@ end
11391164
11401165local function onClick_Sequences (editframe , container , group , unique , path , key , classid , sequencename )
11411166 if # unique < 3 then return end
1167+ -- ponytail: never load a corrupt/broken seq into the editor — the decode
1168+ -- crashes (Serialisation DecodeMessage on unreadable data). Surface it and
1169+ -- stop; use right-click -> Delete to remove it.
1170+ if not GSE .isEmpty (sequencename ) and isBrokenSeq (classid , sequencename ) then
1171+ GSE .Print (" The sequence '" .. tostring (sequencename ) ..
1172+ " ' is corrupt and cannot be opened. Right-click it and choose Delete." )
1173+ return
1174+ end
11421175 SaveLastSequenceEditorPath (group , unique )
11431176 ReleaseEditorFooterButtons (editframe )
11441177
@@ -1407,9 +1440,12 @@ local function ManageTree(editframe)
14071440 }
14081441
14091442 local classtree = {}
1443+ local seenSeq = {}
14101444 local names = GSE .GetSequenceNames ()
14111445
14121446 for k , _ in GSE .pairsByKeys (names , GSE .AlphabeticalTableSortAlgorithm ) do
1447+ -- ponytail: isolate each sequence so one corrupt record can't blank the whole tree
1448+ local ok , err = pcall (function ()
14131449 local elements = GSE .split (k , " ," )
14141450 local tclassid = tonumber (elements [1 ])
14151451 local specid = tonumber (elements [2 ])
@@ -1440,20 +1476,58 @@ local function ManageTree(editframe)
14401476
14411477 GSE .EnsureSequenceLoaded (tclassid , elements [3 ])
14421478 local loadedSeq = GSE .Library [tclassid ] and GSE .Library [tclassid ][elements [3 ]]
1443- if loadedSeq then
1444- for i , j in ipairs (loadedSeq [" Versions" ]) do
1445- table.insert (node .children , {
1446- value = i ,
1447- text = editframe .BuildVersionLabel (tostring (i ), j .Label )
1448- })
1479+ -- ponytail: flag ONLY when the record is actually in the Library and
1480+ -- structurally broken (the real corruption). loadedSeq==nil is NOT proof
1481+ -- of corruption — it usually just means the comma-split key didn't resolve
1482+ -- (e.g. a name that contains a comma), so flagging on nil would false-flag
1483+ -- a healthy seq. A flagged node gets red text + flag icon and no version /
1484+ -- "New Version" children (a click can't re-enter the broken editor);
1485+ -- right-click -> Delete still works (keyed by class+name, not Versions).
1486+ if loadedSeq and GSE .IsSequenceStructurallyBroken (loadedSeq ) then
1487+ node .text = " |cFFFF3030" .. tostring (elements [3 ]) .. " |r"
1488+ node .icon = " Interface\\ DialogFrame\\ UI-Dialog-Icon-AlertNew" -- swap for any flag texture
1489+ else
1490+ if loadedSeq then
1491+ for i , j in ipairs (loadedSeq .Versions ) do
1492+ table.insert (node .children , {
1493+ value = i ,
1494+ text = editframe .BuildVersionLabel (tostring (i ), j .Label )
1495+ })
1496+ end
14491497 end
1498+ table.insert (node .children , {
1499+ text = L [" New" ] .. " " .. L [" Version" ],
1500+ value = " newversion" ,
1501+ icon = Statics .ActionsIcons .Add
1502+ })
14501503 end
1451- table.insert (node .children , {
1452- text = L [" New" ] .. " " .. L [" Version" ],
1453- value = " newversion" ,
1454- icon = Statics .ActionsIcons .Add
1455- })
14561504 table.insert (classtree [tclassid ][specid ], node )
1505+ seenSeq [tclassid .. " |" .. tostring (elements [3 ])] = true
1506+ end )
1507+ if not ok then
1508+ GSE .PrintDebugMessage (" Skipped malformed sequence '" .. tostring (k ) .. " ': " .. tostring (err ), " EDITOR" )
1509+ end
1510+ end
1511+
1512+ -- ponytail: also surface load-corrupt seqs (the decode-broken ones behind the
1513+ -- corrupt-sequence popup) in the tree, red-flagged + deletable, so a user who
1514+ -- Skips/dismisses the popup can still find and remove them. They live in
1515+ -- GSE.CorruptSequences, not the Library, so the loop above never sees them.
1516+ for _ , corrupt in ipairs (GSE .CorruptSequences or {}) do
1517+ local cid , cname = tonumber (corrupt .classid ), corrupt .name
1518+ if cid and cname and not seenSeq [cid .. " |" .. cname ] then
1519+ seenSeq [cid .. " |" .. cname ] = true
1520+ classtree [cid ] = classtree [cid ] or {}
1521+ classtree [cid ][0 ] = classtree [cid ][0 ] or {}
1522+ table.insert (classtree [cid ][0 ], {
1523+ value = cid .. " ,0," .. cname .. " ,0" ,
1524+ text = " |cFFFF3030" .. tostring (cname ) .. " |r" ,
1525+ icon = " Interface\\ DialogFrame\\ UI-Dialog-Icon-AlertNew" ,
1526+ children = {
1527+ { text = L [" Configuration" ], value = " config" , icon = Statics .ActionsIcons .Settings }
1528+ }
1529+ })
1530+ end
14571531 end
14581532
14591533 local subtree = {
0 commit comments