feat(tabs): sharpen default tab layout, hard-reset on v12 -> v13

Aligns the first-run tab layout with the sharpened defaults that
external testers asked for. Three changes in one commit:

1. VanillaGeneral now contains only Say/Yell/Shout. The previous
   30-channel kitchen-sink (party, FC, every linkshell, all gameplay
   events) buried the actual immediate-surroundings conversation
   under loot rolls, crafting and PF pings.
2. HellionSystem absorbs the gameplay-event streams that used to live
   in General — NpcDialogue, LootNotice, LootRoll, Crafting, Gathering,
   PeriodicRecruitmentNotification — plus the announcement and battle-
   system noise (BattleSystem, FreeCompanyAnnouncement,
   PvpTeamAnnouncement) that previously had no fixed home.
3. The first-run / wipe default no longer adds HellionBeginner
   conditionally and no longer adds a static VanillaTellExclusive tab.
   Auto-Tell-Tabs spawns per-conversation tabs on demand, the static
   tell-bucket is redundant. NoviceNetwork users can still add the
   Beginner preset from Settings -> Tabs.

A new v12 -> v13 migration triggers a hard tab-wipe on existing
installs because per-channel mapping from the old General preset to
the new General/System split is ambiguous. The wipe scope is
narrow: only Config.Tabs is cleared, every other knob (Privacy,
Retention, Theme, etc.) keeps its current value. A pre-v13 backup
of the live config is written alongside it for manual restore.
Users see the existing SettingsRefactor migration notification.
This commit is contained in:
2026-05-03 22:48:21 +02:00
parent 26c12c3410
commit 4c18b9a62b
2 changed files with 74 additions and 43 deletions
+55 -9
View File
@@ -190,22 +190,68 @@ public sealed class Plugin : IDalamudPlugin
"SeenPopOutHeaderHint reset to false (v0.6.1 banner re-armed)");
}
// Hellion default tab layout for first-run and v10-wipe.
// General catches player chat plus active gameplay events; the
// System tab takes the technical noise so it does not bury real
// conversation. Beginner tab only appears when the Novice
// Network is enabled in Audio and Notifications, otherwise it
// would just sit empty.
// Hellion Chat v12 → v13 — hard-resets the tab layout to the
// sharpened v1.0.0 defaults (5 thematic tabs, see TabsUtil and
// the default-fill block below). Existing tab state is wiped
// because per-channel mapping from the old General preset to
// the new General/System split would be ambiguous and would
// produce subtly wrong results for users who tweaked the old
// layout. A timestamped backup of the live config is written
// alongside it as a manual restore safety net. The wipe scope
// is intentionally narrow: only Config.Tabs is reset; Privacy,
// Retention, Theme and every other knob keeps its current value.
if (Config.Version < 13)
{
var pluginConfigsDir = Interface.ConfigDirectory.Parent?.FullName;
if (pluginConfigsDir is not null)
{
var liveConfigPath = Path.Combine(pluginConfigsDir, $"{Interface.InternalName}.json");
var backupPath = Path.Combine(pluginConfigsDir, $"{Interface.InternalName}.json.pre-v13-backup");
try
{
if (File.Exists(liveConfigPath))
File.Copy(liveConfigPath, backupPath, overwrite: true);
}
catch (Exception ex)
{
Log.Warning(ex, "HellionChat: pre-v13 config backup failed");
}
}
Config.Tabs.Clear();
Config.Version = 13;
SaveConfig();
Log.Information(
"Migrated config v12 → v13: tab layout hard-reset to v1.0.0 defaults; " +
"pre-v13 config backup written next to the live file. " +
"Default tabs will be populated by the Tabs.Count == 0 block.");
Notification.AddNotification(new Dalamud.Interface.ImGuiNotification.Notification
{
Title = HellionStrings.SettingsRefactor_Migration_Title,
Content = HellionStrings.SettingsRefactor_Migration_Content,
Type = Dalamud.Interface.ImGuiNotification.NotificationType.Info,
InitialDuration = TimeSpan.FromSeconds(25),
});
}
// Hellion v1.0.0 default tab layout. Five thematically separated
// tabs: General catches the immediate-surroundings public chat
// (Say/Yell/Shout) only; System absorbs the rest of the technical
// and gameplay-event noise; FreeCompany, Group and Linkshell each
// own their respective channel set. Tells are not in a static
// tab anymore — Auto-Tell-Tabs spawns dedicated per-conversation
// tabs on demand. Novice-Network gets no preset tab; users who
// want it can add HellionBeginner from Settings → Tabs.
if (Config.Tabs.Count == 0)
{
Config.Tabs.Add(TabsUtil.VanillaGeneral);
Config.Tabs.Add(TabsUtil.HellionSystem);
Config.Tabs.Add(TabsUtil.HellionFreeCompany);
Config.Tabs.Add(TabsUtil.HellionParty);
if (Config.ShowNoviceNetwork)
Config.Tabs.Add(TabsUtil.HellionBeginner);
Config.Tabs.Add(TabsUtil.HellionLinkshell);
Config.Tabs.Add(TabsUtil.VanillaTellExclusive);
}
LanguageChanged(Interface.UiLanguage);
+19 -34
View File
@@ -14,48 +14,20 @@ public static class TabsUtil
return channels;
}
// Hellion-tuned General preset. The pure player-talk catch-all plus
// the active-gameplay event streams (loot, crafting, gathering, NPC
// dialogue, party-finder pings). Pure technical noise (System, Error,
// Login/Logout spam, retainer sales, alarms, sign messages) lives in
// the dedicated System tab so it doesn't bury actual conversation.
// Hellion-tuned General preset (v1.0.0 — sharpened defaults).
// Public-chat-only, the bare three channels you encounter in open
// world. Group/FC/Linkshell traffic moves to dedicated tabs, gameplay
// events (loot, crafting, gathering, NPC dialogue, PF pings) move to
// the System tab where they belong — keeps the General view focused
// on actual conversation in the immediate surroundings.
public static Tab VanillaGeneral => new()
{
Name = Language.Tabs_Presets_General,
SelectedChannels = new Dictionary<ChatType, (ChatSource, ChatSource)>
{
// Player chat
[ChatType.Say] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Yell] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Shout] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Party] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossParty] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Alliance] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.FreeCompany] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.PvpTeam] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell1] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell2] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell3] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell4] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell5] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell6] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell7] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell8] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell1] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell2] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell3] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell4] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell5] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell6] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell7] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell8] = (ChatSourceExt.All, ChatSourceExt.All),
// Active-gameplay events
[ChatType.NpcDialogue] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.LootNotice] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.LootRoll] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Crafting] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Gathering] = (ChatSource.LocalPlayer, ChatSource.LocalPlayer),
[ChatType.PeriodicRecruitmentNotification] = (ChatSourceExt.All, ChatSourceExt.All),
}
};
@@ -130,6 +102,7 @@ public static class TabsUtil
Name = HellionStrings.Tabs_Presets_System,
SelectedChannels = new Dictionary<ChatType, (ChatSource, ChatSource)>
{
// Plain system noise
[ChatType.Debug] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Urgent] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Notice] = (ChatSourceExt.All, ChatSourceExt.All),
@@ -138,10 +111,22 @@ public static class TabsUtil
[ChatType.Echo] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.GatheringSystem] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.NoviceNetworkSystem] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.BattleSystem] = (ChatSourceExt.All, ChatSourceExt.All),
// Login / logout / announcement noise
[ChatType.NpcAnnouncement] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.FreeCompanyAnnouncement] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.FreeCompanyLoginLogout] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.PvpTeamAnnouncement] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.PvpTeamLoginLogout] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.RetainerSale] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.PeriodicRecruitmentNotification] = (ChatSourceExt.All, ChatSourceExt.All),
// Gameplay-event streams (moved out of General in v1.0.0)
[ChatType.NpcDialogue] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.LootNotice] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.LootRoll] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Crafting] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Gathering] = (ChatSourceExt.All, ChatSourceExt.All),
// Misc
[ChatType.Progress] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.RandomNumber] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Orchestrion] = (ChatSourceExt.All, ChatSourceExt.All),