forked from EllesmereGaming/EllesmereUI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEUI__General_Options.lua
More file actions
7723 lines (7158 loc) · 414 KB
/
Copy pathEUI__General_Options.lua
File metadata and controls
7723 lines (7158 loc) · 414 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
-------------------------------------------------------------------------------
-- EUI__General_Options.lua
-- Registers the Global Settings module with EllesmereUI
-- CVar-based settings that apply to all EllesmereUI addons
--
-- Default-application policy:
-- We use C_CVar.GetCVarInfo(name) to get both the current value and
-- Blizzard's built-in default. Our preferred defaults are only applied
-- when the CVar is still sitting at Blizzard's default -- meaning
-- neither the player nor another addon has touched it. If the value
-- differs from the Blizzard default in any way, we leave it alone.
-- Widgets always read the live CVar value so they stay in sync
-- regardless of who set it.
-------------------------------------------------------------------------------
local ADDON_NAME = ...
-------------------------------------------------------------------------------
-- Page / section names
-------------------------------------------------------------------------------
local PAGE_GENERAL = "General"
local PAGE_COLORS = "Fonts & Colors"
local PAGE_PROFILES = "Profiles"
local PAGE_PRESETS = "Presets" -- navigation tab over the presets subpage of the profiles page
local PAGE_WHATSNEW = "Patch Notes"
-- Profiles and Patch Notes are their own sidebar pages (single-page modules),
-- not tabs under Global Settings. These keys match the sidebar buttons created
-- in EllesmereUI.lua.
local PROFILES_KEY = "_EUIProfiles"
local PATCHNOTES_KEY = "_EUIPatchNotes"
-- Standalone single-module builds rename the host addon to contain "Standalone".
-- The What's New tab is suite-only, so it is never added to the page list there.
local IS_STANDALONE = type(ADDON_NAME) == "string" and ADDON_NAME:find("Standalone") ~= nil
-------------------------------------------------------------------------------
-- Shared CDM spell-layout export flow
-- Used by BOTH the full-profile export and the per-addon export. Asks whether
-- to bundle the CDM spell layout (which spells sit on which bars + per-spell
-- settings); on Yes, opens the spec picker so the user chooses which specs.
-- Calls exportFn(includeCDM, cdmSpecs) with the result. An export string is
-- produced ONLY on an explicit "No" (without layout) or a completed picker
-- selection -- closing/escaping either popup produces NO export.
-------------------------------------------------------------------------------
function EllesmereUI.RunCDMSpellExportFlow(activeName, exportFn)
local function pickThenExport()
local specs = {}
local sp = EllesmereUIDB and EllesmereUIDB.spellAssignments
and EllesmereUIDB.spellAssignments.profiles
and EllesmereUIDB.spellAssignments.profiles[activeName]
and EllesmereUIDB.spellAssignments.profiles[activeName].specProfiles
local n = (GetNumSpecializations and GetNumSpecializations()) or 0
for i = 1, n do
local specID = GetSpecializationInfo and GetSpecializationInfo(i)
if specID then
local key = tostring(specID)
local d = sp and sp[key]
specs[#specs + 1] = {
key = key,
checked = (d and type(d.barSpells) == "table" and next(d.barSpells) ~= nil) and true or false,
}
end
end
EllesmereUI:ShowCDMSpecPickerPopup({
title = EllesmereUI.L("Export CDM Spells"),
subtitle = EllesmereUI.L("This can't change which spells the user tracks in Blizzard's CDM.\nIt's recommended to also share your Blizzard CDM layout for any spec you choose here."),
subtitleColor = { 1, 0.82, 0.2 },
subtitleAtBottom = true,
confirmText = EllesmereUI.L("Export"),
specs = specs,
onConfirm = function(selectedSpecs) exportFn(true, selectedSpecs) end,
onCancel = function() end, -- cancel / Esc / click-off: just close, NO export
})
end
EllesmereUI:ShowConfirmPopup({
title = EllesmereUI.L("Include CDM Spell Layout?"),
message = EllesmereUI.L("Include your Cooldown Manager spell layout (which spells sit on which bars) plus all per-spell settings for any specs you choose."),
confirmText = EllesmereUI.L("Yes"),
cancelText = EllesmereUI.L("No"),
onConfirm = function() pickThenExport() end,
onCancel = function() exportFn(false, nil) end, -- "No": export WITHOUT layout
onDismiss = function() end, -- Esc / click-off: just close, NO export
})
end
-------------------------------------------------------------------------------
-- What's New? page -- interactive patch notes in three tiers of importance:
-- 1) hero cards (two per row), 2) small clickable listings, 3) fix lines.
-- Content lives in EllesmereUI._WHATSNEW_PATCHES (newest patch first). A
-- hero/listing entry with a `nav` deep-links to the setting it changed via
-- EllesmereUI:NavigateToElementSettings (opens the page + green-pulses the
-- control); an entry with NO `nav` renders as a static, non-clickable card
-- (for automatic behavior that has no setting to open). Defined at file scope
-- (namespace function) so it adds no locals or upvalues to the deferred
-- options closure below.
-------------------------------------------------------------------------------
function EllesmereUI._BuildWhatsNewPage(pageName, parent, yOffset)
local PP = EllesmereUI.PanelPP
local EG = EllesmereUI.ELLESMERE_GREEN
local PAD = EllesmereUI.CONTENT_PAD
local W = EllesmereUI.Widgets
local MakeFont = EllesmereUI.MakeFont
local MakeBorder = EllesmereUI.MakeBorder
-- This page is a free-form feed, not a DualRow split layout.
parent._showRowDivider = nil
local y = yOffset
local totalW = parent:GetWidth() - PAD * 2
local CARD_GAP = 14
-- Display title: "Module: Title" -- the module name is prepended to every entry.
local function TitleOf(e)
return ((e.module and EllesmereUI.L(e.module) .. ": ") or "") .. (EllesmereUI.L(e.title) or "")
end
-- Stable sort by module display name so same-module entries group together
-- (preserves authored order within a module).
local function SortByModule(list)
local idx = {}
for i, e in ipairs(list) do idx[i] = { e, i } end
table.sort(idx, function(a, b)
local am, bm = a[1].module or "", b[1].module or ""
if am ~= bm then return am < bm end
return a[2] < b[2]
end)
local out = {}
for i = 1, #idx do out[i] = idx[i][1] end
return out
end
-- Deep-link to a setting (opens the page; highlights the control if mapped).
local function GoTo(nav)
if nav and nav.module then
EllesmereUI:NavigateToElementSettings(nav.module, nav.page, nav.section, nav.preSelect, nav.highlight)
end
end
-- Tier 1: a clickable hero card -- dark fill, faint border, green top accent,
-- title + wrapping description, uniform hover lift.
local function MakeHeroCard(x, cy, w, hgt, entry)
local card = CreateFrame("Button", nil, parent)
PP.Size(card, w, hgt)
PP.Point(card, "TOPLEFT", parent, "TOPLEFT", x, cy)
card:SetFrameLevel(parent:GetFrameLevel() + 2)
local bg = card:CreateTexture(nil, "BACKGROUND")
bg:SetAllPoints()
bg:SetColorTexture(0.06, 0.08, 0.10, 0.50)
local brd = MakeBorder(card, 1, 1, 1, 0.12, PP)
local accent = card:CreateTexture(nil, "ARTWORK", nil, 7)
accent:SetColorTexture(EG.r, EG.g, EG.b, 0.6)
PP.Point(accent, "TOPLEFT", card, "TOPLEFT", 1, -1)
PP.Point(accent, "TOPRIGHT", card, "TOPRIGHT", -1, -1)
accent:SetHeight(2)
if PP.DisablePixelSnap then PP.DisablePixelSnap(accent) end
local titleFs = MakeFont(card, 14, nil, EG.r, EG.g, EG.b, 0.9)
PP.Point(titleFs, "TOPLEFT", card, "TOPLEFT", 16, -14)
PP.Point(titleFs, "RIGHT", card, "RIGHT", -16, 0)
titleFs:SetJustifyH("LEFT"); titleFs:SetWordWrap(false)
titleFs:SetText(TitleOf(entry))
local descFs = MakeFont(card, 12, nil, 1, 1, 1, 0.45)
PP.Point(descFs, "TOPLEFT", titleFs, "BOTTOMLEFT", 0, -7)
PP.Point(descFs, "RIGHT", card, "RIGHT", -16, 0)
descFs:SetJustifyH("LEFT"); descFs:SetJustifyV("TOP"); descFs:SetWordWrap(true)
descFs:SetText(EllesmereUI.L(entry.desc) or "")
-- Clickable only when the entry has a nav target. An entry with no nav
-- (automatic behavior with no setting to open -- e.g. party frames in
-- arena) renders as a static card: no hover lift, no click, and mouse
-- disabled so nothing invites a click that would go nowhere.
if entry.nav and entry.nav.module then
card:SetScript("OnEnter", function()
bg:SetColorTexture(0.11, 0.13, 0.15, 0.50); brd:SetColor(1, 1, 1, 0.22)
titleFs:SetAlpha(1)
end)
card:SetScript("OnLeave", function()
bg:SetColorTexture(0.06, 0.08, 0.10, 0.50); brd:SetColor(1, 1, 1, 0.12)
titleFs:SetAlpha(0.9)
end)
card:SetScript("OnClick", function() GoTo(entry.nav) end)
else
card:EnableMouse(false)
end
end
-- Tier 1b: a full-width banner hero (entry.banner = true), styled after
-- the announcement popups (EllesmereUI_RaidFramesPopup /
-- EllesmereUI_PatchNotesPopup): their solid panel fill and white 1px
-- border, the 2px green top accent, a small green eyebrow over a LARGE
-- centered title and centered description, and -- their signature --
-- decorative abstract art built from plain texture bars. Here the art is
-- two mirrored mini bar-charts flanking the text: cost stepping DOWN into
-- a green bar on the left, framerate stepping UP to a green bar on the
-- right. Takes a whole row; height follows the description. Static unless
-- the entry carries a nav.
local function MakeBannerCard(x, cy, w, entry)
local card = CreateFrame("Button", nil, parent)
-- Width FIRST, height provisional: the description anchors LEFT+RIGHT
-- to the card, so the card must already be its real width when the
-- text lays out (and is measured below) -- a width-0 card renders the
-- description as one truncated line instead of wrapping it.
PP.Size(card, w, 100)
PP.Point(card, "TOPLEFT", parent, "TOPLEFT", x, cy)
card:SetFrameLevel(parent:GetFrameLevel() + 2)
local bg = card:CreateTexture(nil, "BACKGROUND")
bg:SetAllPoints()
bg:SetColorTexture(0.06, 0.08, 0.10, 0.92)
local brd = MakeBorder(card, 1, 1, 1, 0.15, PP)
local accent = card:CreateTexture(nil, "ARTWORK", nil, 7)
accent:SetColorTexture(EG.r, EG.g, EG.b, 0.9)
PP.Point(accent, "TOPLEFT", card, "TOPLEFT", 1, -1)
PP.Point(accent, "TOPRIGHT", card, "TOPRIGHT", -1, -1)
accent:SetHeight(2)
if PP.DisablePixelSnap then PP.DisablePixelSnap(accent) end
-- Flanking decorative bar-charts, in the popups' stand-in-texture
-- language (dim white steps, the "now" bar green, a faint baseline).
local BAR_W, BAR_GAP2 = 8, 4
local function MakeChart(anchorSide, inset, heights, alphas)
local groupW = #heights * BAR_W + (#heights - 1) * BAR_GAP2
local base = card:CreateTexture(nil, "ARTWORK")
base:SetColorTexture(1, 1, 1, 0.12)
PP.Size(base, groupW, 1)
if anchorSide == "LEFT" then
PP.Point(base, "LEFT", card, "LEFT", inset, -12)
else
PP.Point(base, "RIGHT", card, "RIGHT", -inset, -12)
end
if PP.DisablePixelSnap then PP.DisablePixelSnap(base) end
for i = 1, #heights do
local bar = card:CreateTexture(nil, "ARTWORK")
local a = alphas[i]
if a == "green" then
bar:SetColorTexture(EG.r, EG.g, EG.b, 0.9)
else
bar:SetColorTexture(1, 1, 1, a)
end
PP.Size(bar, BAR_W, heights[i])
PP.Point(bar, "BOTTOMLEFT", base, "TOPLEFT", (i - 1) * (BAR_W + BAR_GAP2), 1)
if PP.DisablePixelSnap then PP.DisablePixelSnap(bar) end
end
end
-- Left: cost falling to a low green bar. Right: fps rising to a tall
-- green bar.
MakeChart("LEFT", 36, { 34, 26, 19, 13, 8 }, { 0.28, 0.23, 0.18, 0.14, "green" })
MakeChart("RIGHT", 36, { 8, 13, 19, 26, 34 }, { 0.14, 0.18, 0.23, 0.28, "green" })
local eyebrow = MakeFont(card, 11, nil, EG.r, EG.g, EG.b, 0.9)
PP.Point(eyebrow, "TOP", card, "TOP", 0, -18)
eyebrow:SetJustifyH("CENTER"); eyebrow:SetWordWrap(false)
eyebrow:SetText(EllesmereUI.L(entry.eyebrow or "SPECIAL UPDATE"))
-- Banner titles stand alone: no "Module:" prefix, the card IS the
-- event -- and it renders LARGE, like the popups' 26px headline.
local titleFs = MakeFont(card, 24, nil, 1, 1, 1, 1)
PP.Point(titleFs, "TOP", eyebrow, "BOTTOM", 0, -8)
titleFs:SetJustifyH("CENTER"); titleFs:SetWordWrap(false)
titleFs:SetText(EllesmereUI.L(entry.title) or "")
local descFs = MakeFont(card, 13, nil, 1, 1, 1, 0.5)
PP.Point(descFs, "TOP", titleFs, "BOTTOM", 0, -10)
PP.Point(descFs, "LEFT", card, "LEFT", 110, 0)
PP.Point(descFs, "RIGHT", card, "RIGHT", -110, 0)
descFs:SetJustifyH("CENTER"); descFs:SetJustifyV("TOP"); descFs:SetWordWrap(true)
descFs:SetText(EllesmereUI.L(entry.desc) or "")
local dh = math.ceil(descFs:GetStringHeight() or 14)
local bh = 18 + 11 + 8 + 24 + 10 + dh + 28
PP.Size(card, w, bh)
if entry.nav and entry.nav.module then
card:SetScript("OnEnter", function()
brd:SetColor(1, 1, 1, 0.30)
descFs:SetAlpha(0.65)
end)
card:SetScript("OnLeave", function()
brd:SetColor(1, 1, 1, 0.15)
descFs:SetAlpha(0.5)
end)
card:SetScript("OnClick", function() GoTo(entry.nav) end)
else
card:EnableMouse(false)
end
return bh
end
-- Tier 2: a clickable small listing -- title + subtitle, no card chrome, a
-- faint row highlight on hover.
local function MakeListing(cy, w, entry)
local ROW_H = 48
local row = CreateFrame("Button", nil, parent)
PP.Size(row, w, ROW_H)
PP.Point(row, "TOPLEFT", parent, "TOPLEFT", PAD, cy)
local hov = row:CreateTexture(nil, "BACKGROUND")
hov:SetAllPoints()
hov:SetColorTexture(1, 1, 1, 0.07)
hov:SetAlpha(0)
local titleFs = MakeFont(row, 13, nil, 1, 1, 1, 0.9)
PP.Point(titleFs, "TOPLEFT", row, "TOPLEFT", 6, -5)
titleFs:SetJustifyH("LEFT"); titleFs:SetWordWrap(false)
titleFs:SetText(TitleOf(entry))
local subFs = MakeFont(row, 11, nil, 1, 1, 1, 0.4)
PP.Point(subFs, "TOPLEFT", titleFs, "BOTTOMLEFT", 0, -4)
PP.Point(subFs, "RIGHT", row, "RIGHT", -10, 0)
subFs:SetJustifyH("LEFT"); subFs:SetWordWrap(false)
subFs:SetText(EllesmereUI.L(entry.desc) or "")
-- Clickable only when the entry has a nav target (see MakeHeroCard); a
-- nav-less listing renders static with no hover or click.
if entry.nav and entry.nav.module then
row:SetScript("OnEnter", function()
hov:SetAlpha(1); titleFs:SetAlpha(1)
end)
row:SetScript("OnLeave", function()
hov:SetAlpha(0); titleFs:SetAlpha(0.9)
end)
row:SetScript("OnClick", function() GoTo(entry.nav) end)
else
row:EnableMouse(false)
end
return ROW_H
end
-- Tier 3: a plain bug-fix line (bullet + wrapping text, not clickable).
local function MakeFixLine(cy, text)
local dot = MakeFont(parent, 12, nil, EG.r, EG.g, EG.b, 0.55)
PP.Point(dot, "TOPLEFT", parent, "TOPLEFT", PAD + 2, cy - 1)
dot:SetText("\226\128\162") -- bullet glyph (ASCII-safe UTF-8 escape)
local fs = MakeFont(parent, 12, nil, 1, 1, 1, 0.5)
PP.Point(fs, "TOPLEFT", parent, "TOPLEFT", PAD + 18, cy)
PP.Point(fs, "RIGHT", parent, "RIGHT", -PAD, 0)
fs:SetJustifyH("LEFT"); fs:SetWordWrap(true)
fs:SetText(text or "")
local th = fs:GetStringHeight() or 14
return math.max(22, math.ceil(th) + 8)
end
local patches = EllesmereUI._WHATSNEW_PATCHES
if not patches or #patches == 0 then
local none = MakeFont(parent, 13, nil, 1, 1, 1, 0.5)
PP.Point(none, "TOPLEFT", parent, "TOPLEFT", PAD, y - 20)
none:SetText (EllesmereUI.L("No patch notes yet."))
return math.abs(y) + 60
end
-- Intro hint: centered, with 20px of breathing room above and below.
y = y - 20
local hint = MakeFont(parent, 14, nil, 1, 1, 1, 0.5)
PP.Point(hint, "TOP", parent, "TOP", 0, y)
hint:SetJustifyH("CENTER")
hint:SetText (EllesmereUI.L("Click any new feature to go directly to the setting"))
-- Top-left: "New Patch Reminder Dot" opt-out for the pulsing sidebar dot
-- that appears when the account's version increases (see the Patch Notes
-- button in EllesmereUI.lua). Small free-form checkbox on the hint line.
do
local BOX = 14
local row = CreateFrame("Button", nil, parent)
row:SetFrameLevel(parent:GetFrameLevel() + 2)
local box = CreateFrame("Frame", nil, row)
PP.Size(box, BOX, BOX)
PP.Point(box, "LEFT", row, "LEFT", 0, 0)
local boxBg = box:CreateTexture(nil, "BACKGROUND")
boxBg:SetAllPoints()
boxBg:SetColorTexture(0.075, 0.113, 0.141, 1)
local boxBrd = MakeBorder(box, 1, 1, 1, 0.25, PP)
local check = box:CreateTexture(nil, "ARTWORK")
PP.Point(check, "TOPLEFT", box, "TOPLEFT", 3, -3)
PP.Point(check, "BOTTOMRIGHT", box, "BOTTOMRIGHT", -3, 3)
check:SetColorTexture(EG.r, EG.g, EG.b, 1)
local lbl = MakeFont(row, 12, nil, 1, 1, 1, 0.5)
PP.Point(lbl, "LEFT", box, "RIGHT", 7, 0)
lbl:SetText(EllesmereUI.L("New Patch Reminder Dot"))
row:SetSize(BOX + 10 + (lbl:GetStringWidth() or 130), 20)
PP.Point(row, "TOPRIGHT", parent, "TOPRIGHT", -PAD, y + 2)
local function Paint()
local on = not (EllesmereUIDB and EllesmereUIDB.patchDotDisabled)
check:SetShown(on)
if on then
boxBrd:SetColor(EG.r, EG.g, EG.b, 0.85)
else
boxBrd:SetColor(1, 1, 1, 0.25)
end
end
Paint()
row:SetScript("OnClick", function()
if not EllesmereUIDB then EllesmereUIDB = {} end
EllesmereUIDB.patchDotDisabled = (not EllesmereUIDB.patchDotDisabled) and true or nil
Paint()
if EllesmereUI._UpdatePatchDot then EllesmereUI._UpdatePatchDot() end
end)
row:SetScript("OnEnter", function(self)
lbl:SetAlpha(0.85)
if EllesmereUI.ShowWidgetTooltip then
EllesmereUI.ShowWidgetTooltip(self, EllesmereUI.L("Show a pulsing dot on the Patch Notes button whenever EllesmereUI updates to a new version."))
end
end)
row:SetScript("OnLeave", function()
lbl:SetAlpha(0.5)
if EllesmereUI.HideWidgetTooltip then EllesmereUI.HideWidgetTooltip() end
end)
end
y = y - math.ceil(hint:GetStringHeight() or 14) - 20
-- Cap the page to the newest patches (max 10). Older entries may remain in
-- the data table but are not shown; trim them on ship to keep the file tidy.
local MAX_PATCHES = 10
local shown = math.min(#patches, MAX_PATCHES)
for pi = 1, shown do
local patch = patches[pi]
-- A "mini" patch is a bugfix-only release: it carries just a `fixes`
-- tier and renders in a lighter, more compact style so a small patch
-- does not take up as much room as a full feature release.
local isMini = patch.mini
-- Version header. Full patches: large 20px title + neutral divider.
-- Mini patches: compact 15px title with a green "MINI PATCH" tag and a
-- tighter divider.
if isMini then
local ver = MakeFont(parent, 15, nil, 1, 1, 1, 0.9)
PP.Point(ver, "TOPLEFT", parent, "TOPLEFT", PAD, y)
ver:SetText("EllesmereUI " .. (patch.version or ""))
local tag = MakeFont(parent, 10, nil, EG.r, EG.g, EG.b, 0.85)
PP.Point(tag, "LEFT", ver, "RIGHT", 10, -1)
tag:SetText("MINI PATCH")
local uline = parent:CreateTexture(nil, "ARTWORK")
uline:SetColorTexture(1, 1, 1, 0.10)
PP.Size(uline, totalW, 1)
PP.Point(uline, "TOPLEFT", parent, "TOPLEFT", PAD, y - 24)
if PP.DisablePixelSnap then PP.DisablePixelSnap(uline) end
y = y - 34
else
local ver = MakeFont(parent, 20, nil, 1, 1, 1, 0.95)
PP.Point(ver, "TOPLEFT", parent, "TOPLEFT", PAD, y)
ver:SetText("EllesmereUI " .. (patch.version or ""))
local uline = parent:CreateTexture(nil, "ARTWORK")
uline:SetColorTexture(1, 1, 1, 0.12)
PP.Size(uline, totalW, 1)
PP.Point(uline, "TOPLEFT", parent, "TOPLEFT", PAD, y - 32)
if PP.DisablePixelSnap then PP.DisablePixelSnap(uline) end
y = y - 48
end
-- Tier 1: hero cards, two per row. Heroes render in AUTHORED order (the
-- order they appear in the patch's `heroes` table) -- NOT module-sorted
-- like features/fixes -- so each patch can headline whatever matters most
-- first. Reorder the entries in _WHATSNEW_PATCHES to reorder the cards.
local heroes = patch.heroes or {}
if #heroes > 0 then
local cardW = math.floor((totalW - CARD_GAP) / 2)
local CARD_H = 96
-- Sequential layout with column state: normal heroes flow two per
-- row in authored order; a `banner` hero takes a full row of its
-- own, breaking and then resuming the two-column flow. A patch
-- with only two-column heroes consumes exactly the vertical space
-- the old rows-times-height math produced.
local col = 0
for _, hero in ipairs(heroes) do
if hero.banner then
if col == 1 then y = y - CARD_H - CARD_GAP; col = 0 end
local bh = MakeBannerCard(PAD, y, totalW, hero)
y = y - bh - CARD_GAP
else
local cx = PAD + col * (cardW + CARD_GAP)
MakeHeroCard(cx, y, cardW, CARD_H, hero)
col = col + 1
if col == 2 then y = y - CARD_H - CARD_GAP; col = 0 end
end
end
if col == 1 then y = y - CARD_H - CARD_GAP end
y = y + CARD_GAP - 18
end
-- Tier 2: small listings.
local feats = SortByModule(patch.features or {})
if #feats > 0 then
local _, sh = W:SectionHeader(parent, "ADDITIONAL FEATURES", y); y = y - sh
y = y - 5 -- extra spacing below the divider
for _, f in ipairs(feats) do
local rh = MakeListing(y, totalW, f); y = y - rh
end
y = y - 6
end
-- Tier 3: bug-fix lines. Full patches label them under a "BUG FIXES"
-- header; a mini patch is entirely fixes, so the lines render directly
-- beneath the compact header with no redundant section label.
local fixes = SortByModule(patch.fixes or {})
if #fixes > 0 then
if not isMini then
local _, sh = W:SectionHeader(parent, "BUG FIXES", y); y = y - sh
y = y - 10 -- extra spacing below the divider
end
for _, fx in ipairs(fixes) do
local fh = MakeFixLine(y, ((fx.module and EllesmereUI.L(fx.module) .. ": ") or "") .. (EllesmereUI.L(fx.text) or "")); y = y - fh
end
end
if pi < shown then
local _, gap = W:Spacer(parent, y, 24); y = y - gap
end
end
return math.abs(y) + 20
end
-------------------------------------------------------------------------------
-- Patch-notes content for the What's New page (newest patch first). Each hero
-- and listing entry's `nav` deep-links to the setting it changed via
-- EllesmereUI:NavigateToElementSettings(module, page, section, preSelect, highlight).
-------------------------------------------------------------------------------
EllesmereUI._WHATSNEW_PATCHES = {
{
version = "8.7.5",
heroes = {
{
-- Perf + swipe-latency story: nothing to open, renders static.
module = "Action Bars",
title = "Performance & Instant Swipes",
desc = "Another deep performance pass across the action bar engine, and cooldown swipes now start the moment you press the key instead of waiting on the server, with a fix for swipes starting late while spamming a keybind.",
},
{
module = "Blizz UI Enhanced",
title = "Loot Reskin Suite",
desc = "The whole loot window collection in EllesmereUI style: the loot window with quality-colored icon borders and a clean hover, the need / greed roll popups, the pending-rolls window, and loot toasts with quality strips, and a scale slider.",
nav = { module = "EllesmereUIBlizzardSkin", page = "Blizzard Window Skins" },
},
},
features = {
{
module = "Action Bars",
title = "Auto-Paging Opt-Outs",
desc = "Keep Bar 1 put through forms, stances, and skyriding",
nav = { module = "EllesmereUIActionBars", page = "Bar Display", section = "PAGING", highlight = "Disable Form Paging" },
},
{
-- The window-skin style cards are hand-built chrome with no
-- highlightable rows: page-only nav for all four.
module = "Blizz UI Enhanced",
title = "Group Invite Popup Reskin",
desc = "The group invite dialogs, role checks included",
nav = { module = "EllesmereUIBlizzardSkin", page = "Blizzard Window Skins" },
},
{
module = "Party Mode",
title = "Spinning Action Bars",
desc = "Buttons orbit their bars; speed slider in the cog",
nav = { module = "EllesmereUIPartyMode", page = "Party Mode", highlight = "Spinning Action Bars" },
},
{
module = "Quality of Life",
title = "Raid Tools Grow Direction",
desc = "Pick which way the windows open from the icon",
nav = { module = "EllesmereUIQoL", page = "Raid Tools", section = "GENERAL", highlight = "Menu Grow Direction" },
},
{
module = "Unit Frames",
title = "Elite/Rare Indicator",
desc = "Dragon badge on elite and rare targets",
nav = { module = "EllesmereUIUnitFrames", page = "Main Frames", section = "EXTRAS", highlight = "Elite/Rare Indicator",
preSelect = function()
if EllesmereUI._setUnitFrameUnit then EllesmereUI._setUnitFrameUnit("target") end
end },
},
},
fixes = {
{ module = "Action Bars", text = "Buttons no longer stay red out of range while you stand in melee" },
{ module = "Action Bars", text = "Empowered spells no longer revert to Press-and-Tap after a loading screen" },
{ module = "Action Bars", text = "Dragging a spell in combat now reveals empty slots with Always Show Buttons off" },
{ module = "Blizz UI Enhanced", text = "Great Vault now wears the shared Window Skins border and buttons" },
{ module = "Chat", text = "Tab chrome no longer draws over the maximized world map" },
{ module = "Cooldown Manager", text = "Focus Kick cast sound no longer goes silent after loading screens" },
{ module = "Localization", text = "Updated Traditional Chinese, Simplified Chinese, German, and Korean translations" },
{ module = "Quality of Life", text = "FPS optimizer now sets Spell Density to Essential as intended" },
{ module = "Raid Frames", text = "Layout no longer drifts after leaving a raid with a custom raid-size override" },
},
},
{
version = "8.7.4",
heroes = {
{
-- Pure performance work: nothing to open, renders static.
module = "Action Bars",
title = "Performance Upgrade",
desc = "Hovering with Show All on Mouseover has been significantly optimized, and bars hidden by visibility conditions now cost zero CPU while hidden. Combat event handling across range, glows, stance, and pet bars was rebuilt to do the minimum work possible.",
},
},
features = {
{
-- The toggle lives in the Cooldown Text cog on this row.
module = "Action Bars",
title = "Fit Cooldown Text to Button",
desc = "Optional per-bar cap so countdown text stays inside small buttons",
nav = { module = "EllesmereUIActionBars", page = "Bar Display", section = "TEXT", highlight = "Cooldown Text Size" },
},
{
-- The toggle lives in the currency block's own settings
-- popup, so the nav is page-only.
module = "Data Bars",
title = "Currency Description Toggle",
desc = "Hide the long description text in the currency block's tooltip",
nav = { module = "EllesmereUIDataBars", page = "DataBars" },
},
{
-- The toggle lives in the Background row's cog; the row
-- label is dynamic ("Background (Class Resource)" while
-- split), so the highlight matches the default state only.
module = "Resource Bars",
title = "Unique Backgrounds Per Bar",
desc = "Give Health and Power bars separate background colors and opacity",
nav = { module = "EllesmereUIResourceBars", page = "Class, Power and Health Bars", section = "BAR DISPLAY", highlight = "Background" },
},
},
fixes = {
{ module = "Action Bars", text = "Cancelling a cast now clears the cooldown swipe immediately instead of letting the full sweep play out." },
{ module = "Action Bars", text = "Out-of-range coloring now tracks correctly across page flips and slots shared between bars." },
{ module = "Action Bars", text = "Cooldown text renders at exactly your configured size again; the 8.7.3 small-button cap is now the opt-in Fit Size to Button toggle." },
{ module = "Action Bars & Cooldown Manager", text = "Hide Count at 0 no longer hides the charge number for spells that keep a cooldown while holding charges, such as Roll, Feint, and Survival of the Fittest." },
{ module = "Damage Meters", text = "Window titles no longer truncate against hidden header icons when Hide Icons Until Hover is on." },
{ module = "Data Bars", text = "Databar tooltips now layer above other tooltips, and description text uses the tooltip's full width." },
{ module = "Localization", text = "Updated Korean (koKR) translations for the latest options." },
{ module = "Minimap", text = "The expansion landing button no longer reappears next to a replacement button from another addon." },
{ module = "PTR Auras", text = "Buff duration text no longer flashes 0 for a moment when crossing under one minute." },
{ module = "Quality of Life", text = "Auto Open Containers no longer cancels your casts, and waits for the mailbox to close before opening deliveries." },
{ module = "Quality of Life", text = "Guild repair messages now report the true payer when Auto Sell Junk runs during the same visit." },
},
},
{
version = "8.7.3",
heroes = {
{
-- Vertical Fill lives in the Health Bar Texture row's cog
-- (cog-only controls have no _labelText), so the highlight
-- targets the owning row.
module = "Raid & Unit Frames",
title = "Vertical Health Bars",
desc = "Health bars can now fill bottom-to-top on raid, party, and every unit frame. Absorbs, heal prediction, and the bar background follow the same axis, and Reverse Fill flips the direction to top-to-bottom.",
nav = { module = "EllesmereUIRaidFrames", page = "Frames", section = "HEALTH BAR", highlight = "Health Bar Texture" },
},
{
module = "Chat",
title = "True Hide & Click-Through",
desc = "Chat at Fade Strength 100 or hidden by visibility rules is now completely gone: clicks, camera drags, and targeting pass straight through to the world, and mouseover still wakes the faded chat.",
nav = { module = "EllesmereUIChat", page = "Chat", section = "IDLE FADE", highlight = "Fade Strength" },
},
},
features = {
{
module = "Chat",
title = "Scroll Button on Chat Panel",
desc = "Anchor the scroll-to-bottom arrow to the chat's corner like default UI",
nav = { module = "EllesmereUIChat", page = "Sidebar", section = "ICONS", highlight = "Scroll Button on Chat Panel" },
},
{
-- Tab Offset X is a cog-popup row (no _labelText); the
-- highlight targets the Inner Padding X row that owns the cog.
module = "Chat",
title = "Tab Offset X",
desc = "Shift the tab strip so corner-flush chat never clips a tab",
nav = { module = "EllesmereUIChat", page = "Tabs", section = "LAYOUT", highlight = "Inner Padding X" },
},
{
-- Anchor choices live in the Breakdown cog; the highlight
-- targets the owning row.
module = "Damage Meters",
title = "Breakdown Anchor Positions",
desc = "Show the hover breakdown beside the window or centered",
nav = { module = "EllesmereUIDamageMeters", page = "Damage Meters", section = "BARS", highlight = "Show Breakdown on Hover" },
},
{
-- No setting to open: pure interaction change, renders static.
module = "Damage Meters",
title = "Header Right-Click",
desc = "Right-click the window header to switch meter type",
},
{
-- Show Decimal lives in the Standalone Combat Timer cog.
module = "Damage Meters",
title = "Standalone Timer Decimal",
desc = "Optional tenths display on the standalone combat timer",
nav = { module = "EllesmereUIDamageMeters", page = "Damage Meters", section = "STANDALONE COMBAT TIMER", highlight = "Standalone Combat Timer" },
},
{
module = "Mythic+ Timer",
title = "Count / Total + Remaining",
desc = "New enemy forces text format, e.g. 188/240 (52 left)",
nav = { module = "EllesmereUIMythicTimer", page = "Mythic+ Timer", section = "FORCES", highlight = "Enemy Text Format" },
},
{
-- The slider lives in each aura slot's cog on the Core
-- Positions grid (custom chrome, no highlightable rows), so
-- the nav is section-only.
module = "Nameplates",
title = "Adjust Crop",
desc = "Set how much cropped aura icons trim, per element",
nav = { module = "EllesmereUINameplates", page = "Display", section = "CORE POSITIONS" },
},
{
-- The toggle lives in the Texture row's cog.
module = "Resource Bars",
title = "Blizzard Bar Artwork",
desc = "Class Resource bar can use Blizzard's default bar art",
nav = { module = "EllesmereUIResourceBars", page = "Class, Power and Health Bars", section = "BAR DISPLAY", highlight = "Texture" },
},
{
-- Both toggles live in the Spell ID cog on this row.
module = "Tooltips",
title = "Icon ID & Item ID Toggles",
desc = "Turn each tooltip ID line off individually",
nav = { module = "EllesmereUIBlizzardSkin", page = "Tooltips, Menus & Popups", section = "BLIZZARD TOOLTIP", highlight = "Show Spell ID on Tooltip" },
},
},
fixes = {
{ module = "Action Bars", text = "Cooldown countdown text now scales down on small buttons instead of overflowing them." },
{ module = "Action Bars", text = "Empowered spells no longer flip to Press and Tap behavior after mounting between pulls." },
{ module = "Chat", text = "Clicks and camera drags pass through the visible chat like the default UI." },
{ module = "Chat", text = "Hidden sidebar icons are no longer clickable and no longer show tooltips." },
{ module = "Chat", text = "Panel border no longer draws above the EllesmereUI settings window." },
{ module = "Cooldown Manager", text = "Suppress GCD now covers the final moments of a charge recharge." },
{ module = "Damage Meters", text = "Combat timer ticks smoothly every second regardless of the refresh rate." },
{ module = "Localization", text = "Updated Korean (koKR) translations for the latest options." },
{ module = "Minimap", text = "The middle-click menu is now translated on every language and uses your minimap font." },
{ module = "Quality of Life", text = "Movement Alert countdown no longer snaps to 0.0 when combat starts in instances." },
{ module = "Unit Frames", text = "Kick tracking now follows the summoned demon's interrupt for Demonology Warlocks." },
{ module = "PTR Tooltips", text = "Buff tooltips no longer show the spell ID twice when no modifier is set." },
{ module = "PTR Unit Frames", text = "No more gap under the frame when the cast bar is moved away in unlock mode." },
},
},
{
version = "8.7.2",
mini = true,
fixes = {
{ module = "Cooldown Manager", text = "Fixed the Edit Mode update popup reappearing on every login for a small number of players, leaving them stuck in a reload loop. It now asks once, and if the change still cannot be saved it explains how to set it manually." },
{ module = "General", text = "The options panel and its popups now scale to your display, so they are no longer around half size on 4K and 5K monitors." },
{ module = "General", text = "Fixed popups being scaled twice, which made them bigger than intended and made them grow as you lowered your UI Scale. They are now a consistent size on every display, which can look slightly smaller than before at some UI Scale settings." },
{ module = "General", text = "The first install window can no longer open larger than your screen, which could put its buttons off display with no way to close it." },
{ module = "General", text = "The options panel scale is set once on displays above 1440p to match the corrected default. Any size you pick after that is kept." },
{ module = "Nameplates", text = "Long friendly player names no longer get cut off." },
{ module = "Nameplates", text = "Player titles now show inline with the name instead of on their own line below it." },
{ module = "Nameplates", text = "The guild name now sits on its own line below the name, with its own Guild Text Color control for custom or class color." },
{ module = "Nameplates", text = "Subtitle Text Size has been removed. The guild line now follows the name's font size." },
{ module = "Resource Bars", text = "Fixed Balance Druid hash lines disappearing after shifting to cat or bear form and back, staying gone until a reload." },
{ module = "Resource Bars", text = "Shift Elements if No Power now works when the power bar is hidden by Hide Power Bar if Resource, instead of leaving a gap where the bar would have been." },
},
},
{
version = "8.7.1",
heroes = {
{
module = "Nameplates",
title = "Title and Guild Subtitles",
desc = "Friendly players can now show a smaller line under their name with their title, guild, or both, in both full health bar plates and Name Only mode. Text size, a custom or class color, and the angle brackets around guild names are all configurable.",
nav = { module = "EllesmereUINameplates", page = "General", section = "OTHER NAMEPLATES", highlight = "Subtitle Text" },
},
{
-- Section header lives in the shared BATTLE RES section builder
-- (EUI_QoL_BattleRes_Options.lua), which the QoL page embeds.
-- The duplicate header in the file's own page builder is dead
-- code with no callers, so it cannot shadow this one.
module = "Battle Res",
title = "Text Display Style",
desc = "The tracker can now be shown as a compact text line with the charge count, a separator, and the time until the next charge, instead of the Rebirth icon. Timer color, count color, text size, font, and outline each get their own settings.",
nav = { module = "EllesmereUIQoL", page = "QoL", section = "BATTLE RES", highlight = "Display Style" },
},
},
features = {
{
-- The same toggle ships on Cooldown Manager's ICON DISPLAY
-- section; one entry covers both and points at Action Bars.
-- preSelect is REQUIRED, not decorative: ICON EFFECTS is built
-- by BuildSharedBarSettings, which is skipped entirely whenever
-- the persisted bar selection is a visibility-only bar.
module = "Action Bars",
title = "Hide Charge Count at 0",
desc = "Also on Cooldown Manager bars",
nav = { module = "EllesmereUIActionBars", page = "Bar Display", section = "ICON EFFECTS", highlight = "Hide Charge Count at 0",
preSelect = function()
if EllesmereUI._setActionBarKey then EllesmereUI._setActionBarKey("MainBar") end
end },
},
{
module = "Bags",
title = "Merge Duplicate Items",
desc = "Turn merging off to keep slots separate",
nav = { module = "EllesmereUIBags", page = "Bags", section = "DISPLAY", highlight = "Merge Duplicate Items" },
},
{
-- Pet is only selectable on the Mini Frames page (Main Frames'
-- selector offers player/target/focus only), and the toggle
-- sits in the Enable Pet Frame row's left Frame Source cog, so
-- the highlight targets that owning row.
module = "Unit Frames",
title = "Always Show Pet Frame",
desc = "Pet ignores your frame visibility rules",
nav = { module = "EllesmereUIUnitFrames", page = "Mini Frames", section = "DISPLAY", highlight = "Enable Pet Frame",
preSelect = function()
if EllesmereUI._setMiniUnit then EllesmereUI._setMiniUnit("pet") end
end },
},
{
-- The Width % sliders are cog-popup rows built with label=,
-- which DualRow never tags into _labelText, so the highlight
-- targets the Left Text row that owns the cog.
module = "Unit Frames",
title = "Text Width %",
desc = "Per slot width for name and text rows",
nav = { module = "EllesmereUIUnitFrames", page = "Main Frames", section = "HEALTH BAR", highlight = "Left Text",
preSelect = function()
if EllesmereUI._setUnitFrameUnit then EllesmereUI._setUnitFrameUnit("player") end
end },
},
},
fixes = {
{ module = "Action Bars", text = "Mac Command key bindings now abbreviate correctly in hotkey text on action buttons and Cooldown Manager icons, instead of showing the raw META prefix." },
{ module = "Bags", text = "Merged stacks now split back apart automatically while the Send Mail tab, a trade, the auction house, your bank, or a guild bank is open, then re-merge once those close, so you can reach every individual slot." },
{ module = "Blizz UI Enhanced", text = "Inspecting a new player right after someone else no longer leaves the previous target's item level, enchant, and upgrade track labels on the gear slots." },
{ module = "Cooldown Manager", text = "Only Show Numbers on buff bars now follows the bar's own Cooldown Text setting and any per icon override, instead of forcing the countdown on. If you had Cooldown Text turned off on one of those bars, those icons now show only the stack count, so turn Cooldown Text back on to bring the number back." },
{ module = "Data Bars", text = "The Travel block now shows a dash and treats a hearthstone or Mythic+ teleport as still cooling when its cooldown data is unreadable in restricted combat, instead of throwing an error." },
{ module = "General", text = "Long setting labels now truncate with an ellipsis and show their full text on hover, instead of wrapping onto a second line or running under the control beside them." },
{ module = "Movement Alert", text = "Icon display mode now shows the cooldown swipe and its countdown number reliably, including in the moment right after a cast, and no longer depends on Blizzard's Cooldown Timer Text setting being on." },
{ module = "Raid Frames", text = "Buff icons created for the first time during combat no longer swallow clicks and mouseover for the rest of that fight, so click casting works through them immediately. Their aura tooltip comes back when combat ends." },
{ module = "Unit Frames", text = "Auras removed at the same moment their data updates, such as dispels, trap breaks, and fully consumed absorbs, no longer leave a stuck icon behind with no tooltip, and reapplying the same aura no longer duplicates it." },
{ module = "Unit Frames", text = "Name Length and Show Ellipsis have been replaced by a per slot Width % setting, so text is now trimmed by how much room it has rather than by a character count. Any Name Length you had set no longer applies and names show at full length until you lower Width %." },
{ module = "Unit Frames", text = "The combat indicator custom color swatch now dims and blocks clicks when it does not apply, instead of disappearing and shifting the row spacing." },
},
},
{
version = "8.7",
mini = true,
fixes = {
{ module = "Cooldown Manager", text = "Hide Active State now greys transformed charge spells (e.g. Judgment under Avenging Wrath) at zero charges in real combat, reading the transformed spell's own cooldown." },
{ module = "Mythic+ Timer", text = "Fixed the floating timer appearing in the wrong place at the start of each key when the timer is scaled, drifting toward the center of the screen until Unlock Mode was opened." },
{ module = "Nameplates", text = "Pandemic and dispel glows no longer cover the duration and stack text on nameplate auras." },
{ module = "Quality of Life", text = "Hide Item Transformations no longer hides the Atomically Recalibrator and Atomically Regoblinator toy effects by default." },
{ module = "Raid Frames", text = "Frames now show OFFLINE instead of DEAD when a player is both disconnected and dead." },
{ module = "Raid Frames", text = "Fixed action blocked errors when buff indicators built their icons for the first time during combat, such as on delve trash pulls." },
{ module = "Unit Frames", text = "Fixed buffs and debuffs keeping the previous target's icons when switching targets." },
},
},
{
version = "8.6.8",
heroes = {
{
-- Full-width banner card (banner = true, see MakeBannerCard):
-- announcement-style chrome dedicated to the suite-wide
-- performance overhaul. Static on purpose -- the speedup is
-- automatic, there is no setting to open.
banner = true,
eyebrow = "SUITE-WIDE OPTIMIZATION",
title = "The Performance Patch",
desc = "The entire suite has been rebuilt for speed: CPU Usage has been cut by more than 70% while idle, and over 50% during M+/Raid combat. Same look, same features, at a fraction of the cost.",
},
},
fixes = {
{ module = "Action Bars", text = "The micro menu and bag bar reappear on their own after wild pet battles." },
{ module = "Action Bars", text = "Clicking an empty stretch of an action bar no longer flips the main bar to another page." },
{ module = "Action Bars", text = "Cooldown swipes repaint when a proc modifies them, and an active GCD no longer greys out charge spells." },
{ module = "Blizz UI Enhanced", text = "Context menus keep their skin after the first menu of the session." },
{ module = "Blizz UI Enhanced", text = "Submenu flyouts (Loot Specialization, Raid Markers and friends) are skinned again." },
{ module = "Blizz UI Enhanced", text = "Fixed repeating errors when hovering enemy nameplate auras inside instances." },
{ module = "Cooldown Manager", text = "Replaced tracked buffs (e.g. Wither for Hellcaller) show the castable spell's icon instead of the aura's." },
{ module = "Cooldown Manager", text = "Transforming cooldowns like Holy Armaments stay on the bar you assigned them to." },
{ module = "Cooldown Manager", text = "Custom Active States (e.g. trinket glows) work after login without opening the settings first." },
{ module = "Cooldown Manager", text = "Pandemic Glow's None option is now selectable and actually hides Blizzard's pandemic glow." },
{ module = "Cooldown Manager", text = "Suppress GCD now covers racials and user-added spells." },
{ module = "Cooldown Manager", text = "Transformed charge spells (e.g. Judgment under Avenging Wrath) grey out at zero charges with Hide Active State." },
{ module = "Cooldown Manager", text = "Bar Glows light up when the aura is gained, not only after one is removed." },
{ module = "General", text = "Typing a value into a slider's number box now updates dependent controls the same as dragging it." },
{ module = "General", text = "Many missing translations now translate on non-English clients; Traditional Chinese and Korean translations expanded (community)." },
{ module = "Quality of Life", text = "The Upgrade Calculator works on non-English clients: crest totals, missing upgrades and the queue no longer read zero." },
{ module = "Quality of Life", text = "The Raid Tools window keeps its saved position correctly when scaled." },
{ module = "Unit Frames", text = "More absorb bar position options." },
{ module = "Unit Frames", text = "With Only Dispellable by You, dwarves now get the dispel overlay for bleeds (Stoneform clears them)." },
},
},
{
version = "8.6.6",
heroes = {
{
-- Umbrella card: absorbs the pull-timer boss-mod sync, the
-- combat-safe markers, and the auto-show/collapse/keybind work
-- rather than spawning sibling feature cards beside itself.
module = "Quality of Life",
title = "Raid Tools Panel",
desc = "A new movable panel with ready check, role check, convert or disband, one click pull timers, and target/world markers that work in combat. Show it as one or two windows at any scale, collapse it to an icon, and open it from a keybind.",
nav = { module = "EllesmereUIQoL", page = "Raid Tools", section = "GENERAL", highlight = "Show Raid Tools" },
},
},
features = {
{
module = "Chat",
title = "Input Field Size and Font",
desc = "Set the chat box height, font and size",
nav = { module = "EllesmereUIChat", page = "Chat", section = "INPUT FIELD", highlight = "Edit Box Height" },
},
{
module = "Chat",
title = "Sidebar Width",
desc = "Size the sidebar from 30 to 100 pixels",
nav = { module = "EllesmereUIChat", page = "Sidebar", section = "SIDEBAR", highlight = "Sidebar Width" },
},
{
module = "General",
title = "Name Font",
desc = "Own font for floating names; needs a logout",
nav = { module = "_EUIGlobal", page = "Fonts & Colors", section = "GLOBAL FONT", highlight = "Name Font" },
},
{
-- Title carries no module word: TitleOf prefixes "Party Mode: ",
-- and the option's own label ends in "on Party Mode", which would
-- read twice. The row is a direct W:Dropdown call, which still
-- tags _labelText from its text argument, so the label matches.
module = "Party Mode",
title = "Activation Sound",
desc = "Play a chosen sound when it turns on",
nav = { module = "EllesmereUIPartyMode", page = "Party Mode", section = "PARTY MODE", highlight = "Play Sound on Party Mode" },
},
{
-- Lives as the "Anchor to Debuffs" VALUE inside the Buff Display
-- dropdown, so the highlight targets that row (its DualRow label
-- starts "Buff Display", and it is the first row under the
-- header, so nothing can intercept the match). preSelect is
-- REQUIRED, not optional: the BUFFS AND DEBUFFS section only
-- builds for player/target/focus, so anyone whose last viewed
-- unit was pet or boss would land on a page without the section.
module = "Unit Frames",
title = "Anchor to Debuffs",
desc = "Buffs show as the first rows of your debuff stack",
nav = { module = "EllesmereUIUnitFrames", page = "Main Frames", section = "BUFFS AND DEBUFFS", highlight = "Buff Display",
preSelect = function()
if EllesmereUI._setUnitFrameUnit then EllesmereUI._setUnitFrameUnit("player") end
end },
},
},
fixes = {
{ module = "Action Bars", text = "Reduced CPU usage while Assisted Combat (One Button Assist) is active: a new suggested spell now updates just that button, instead of running a full pass over every button on every bar each time the rotation moves on." },
{ module = "Bags", text = "TradeSkillMaster's Banking UI now detects when you switch between your character bank and the warbank from the sidebar, instead of staying on the wrong bank type." },
{ module = "Blizz UI Enhanced", text = "Fixed right-clicking a unit and choosing Whisper sometimes opening the chat box with a broken, unreadable recipient name and spamming repeated errors." },
{ module = "Chat", text = "Fixed undocked windows creeping toward the bottom-left corner of the screen on every login or reload." },
{ module = "Chat", text = "Turning on Input on Top now grows the chat panel upward to fit the input box, instead of placing it inside the panel and shrinking the area your chat text has to work with." },
{ module = "Chat", text = "Fixed windows you create and dock permanently sometimes being sized like a temporary whisper tab, and tabs losing their custom colors after moving or resizing the frame in Blizzard's Edit Mode." },
{ module = "Chat", text = "The Tab Texture option, renamed from Tab Background Texture, now works whether or not Sync Border with Chat Panel is on, instead of staying greyed out." },
{ module = "Chat", text = "A Mouseover sidebar now only takes up panel space while it is actually showing, so with Tabs Inside Chat Panel or Align Tabs to Full Panel the panel and tab alignment resize as you move the mouse on and off it, where before that space was reserved at all times." },
{ module = "Chat", text = "Tab borders, dividers and the active underline now line up again immediately after changing Tab Spacing, instead of staying at their old positions until something else redrew the tabs." },
{ module = "Chat", text = "Tab dividers now sit in the gap between tabs rather than on the tab's own edge, and temporary whisper tabs no longer draw one." },
{ module = "Chat", text = "Tab Background Color and Tab Background Color Active are now color swatches, with their opacity moved into the cog beside each row." },
{ module = "Chat", text = "Tab fonts, the active tab font and the active tab background can now be set to Accent Color or Class Color." },
{ module = "Chat", text = "The Active Underline's third color preset is now Class Color instead of Border Color, so an underline that was set to Border Color now shows your Custom Color instead." },
{ module = "Chat", text = "Fixed another source of repeating error messages when receiving a whisper, or when a Battle.net whisper toast appeared, while the sender's name was hidden by the game such as during a Mythic+ key." },
{ module = "Cooldown Manager", text = "Fixed an inactive tracked buff's placeholder icon showing the pre-talent spell's art, such as a Hellcaller Destruction Warlock's Immolate slot that actually casts Wither. The icon's tooltip follows the same correction, and the per-icon preview in the options page shows the corrected art." },
{ module = "Cooldown Manager", text = "Turning off a bar's Pandemic Glow now clears a glow already lit on an icon straight away, instead of leaving it stuck on screen until you turned the setting back on, let the buff expire, then turned it off again." },
{ module = "Cooldown Manager", text = "Custom and preset buff icons now use the Cooldown Swipe Color you picked for them, instead of falling back to the cooldown style swipe handling meant for ability cooldowns." },
{ module = "Cooldown Manager", text = "Setting up or editing a Generic CDs/Buffs sync now tells you in chat how many specs were included and that icon order is not synced, and says when confirming with only one spec ticked cleared an existing sync instead of creating one." },
{ module = "Cooldown Manager", text = "The Health Potion preset now shows and tracks the newest health potion first, falling back to the Silvermoon potions when you have none of the new ones." },
{ module = "General", text = "Tooltips inside the EllesmereUI options panel and its popups now follow your EUI Options Panel Scale setting, instead of always showing at the default size." },
{ module = "General", text = "The Mushroom hearthstone toy is now included, so it can be picked in the Data Bars Travel block and shows in the Chat and Minimap portal flyouts." },
{ module = "General", text = "Account Wide Interface Settings no longer triggers an Incompatible Addon Detected warning on login for Quest Tracker." },
{ module = "General", text = "Added and corrected translations across German, Spanish, French, Italian, Portuguese, Russian, Korean, Simplified Chinese and Traditional Chinese." },
{ module = "Nameplates", text = "Nameplate text slots can now show a unit's level, on its own or alongside the name." },
{ module = "PTR Nameplates", text = "Fixed the Caster nameplate color on PTR, it now applies to any unit with a mana bar." },
{ module = "PTR Unit Frames", text = "Focus, focus target and target of target frames show class colors for allied players again, instead of falling back to the plain green friendly color. Those three frames use Blizzard's standard class colors, so a custom class color addon cannot recolor them." },
{ module = "Quality of Life", text = "Auto Repair now uses whatever the guild bank can contribute and charges you only the remainder, instead of charging your own gold for the whole bill any time the guild bank could not cover it in full. It also no longer refuses to repair when your own gold is short but your gold plus guild funds would cover it." },
{ module = "Resource Bars", text = "Fixed vertical Health Bar, Power Bar and Class Resource bars showing a sideways box and swapped size numbers in Unlock Mode, so dragging a handle resized the wrong axis. On all four bars, including the GCD Bar, the Height and Width Match options now grey out the slider they actually control. Horizontal bars were not affected." },
{ module = "Resource Bars", text = "Fixed the Protection Warrior Ignore Pain bar's stack count text going blank and staying blank until Blizzard's tracked buff viewer happened to reuse the same icon slot." },
{ module = "Spec Overrides", text = "Fixed a spec or conditional override captured on a custom raid size (10, 15, 25 or 30 man) silently never taking effect, and continuing to fail on later edits to that tier. New overrides now save correctly, and profiles carrying the earlier ones repair themselves with nothing for you to do." },
{ module = "Spec Overrides", text = "Fixed old profile corruption that could cause switching to a different profile while a spec-specific Unlock Mode layout was active to leave the old layout's frame positions on screen and then save them over your regular layout. Positions now resync immediately instead." },
{ module = "Unit Frames", text = "Fixed the Absorb Short health text getting stuck on a leftover 0 on target, focus, boss and pet frames after the unit changed or died. The player frame was never affected." },
},
},
{
version = "8.6.5",
-- No hero tier: 8.6.5 is a maintenance release whose largest additions
-- are single toggles. `_BuildWhatsNewPage` skips the hero block when
-- `heroes` is absent, and this is NOT a mini patch (a features tier is
-- present), so the version title still renders full size.
features = {
{
-- Page-only nav on purpose. Both new Cooldown Saturation rows
-- are MakeSubnavRow entries inside the per-icon spell picker
-- popup, which never gets a _labelText or _isSectionHeader, so
-- any section/highlight would fall through the match loop and
-- no-op. The popup opens off the live preview in the page's
-- fixed content header, so this lands one click away.
module = "Cooldown Manager",
title = "Cooldown Saturation",
desc = "Keep icons colored while on cooldown",
nav = { module = "EllesmereUICooldownManager", page = "CDM Bars" },
},
{
-- PTR entry: the socialui window pack gates on
-- Blizzard_SocialUI, which does not exist on 12.0, so this is