can drag chat tabs around as much as u want

syncshell tabs can use notes instead by rightclicking and prefering it
added some visibility settings (hide in combat, etc)
and cleaned up some of the ui
This commit is contained in:
2025-12-21 01:17:00 +09:00
parent e5fa477eee
commit ab369d008e
7 changed files with 493 additions and 22 deletions

View File

@@ -23,6 +23,7 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
private readonly DalamudUtilService _dalamudUtilService;
private readonly ActorObjectService _actorObjectService;
private readonly PairUiService _pairUiService;
private readonly ChatConfigService _chatConfigService;
private readonly Lock _sync = new();
@@ -57,6 +58,7 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
_dalamudUtilService = dalamudUtilService;
_actorObjectService = actorObjectService;
_pairUiService = pairUiService;
_chatConfigService = chatConfigService;
_isLoggedIn = _dalamudUtilService.IsLoggedIn;
_isConnected = _apiController.IsConnected;
@@ -136,6 +138,42 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
}
}
public void MoveChannel(string draggedKey, string targetKey)
{
if (string.IsNullOrWhiteSpace(draggedKey) || string.IsNullOrWhiteSpace(targetKey))
{
return;
}
bool updated = false;
using (_sync.EnterScope())
{
if (!_channels.ContainsKey(draggedKey) || !_channels.ContainsKey(targetKey))
{
return;
}
var fromIndex = _channelOrder.IndexOf(draggedKey);
var toIndex = _channelOrder.IndexOf(targetKey);
if (fromIndex < 0 || toIndex < 0 || fromIndex == toIndex)
{
return;
}
_channelOrder.RemoveAt(fromIndex);
var insertIndex = Math.Clamp(toIndex, 0, _channelOrder.Count);
_channelOrder.Insert(insertIndex, draggedKey);
_chatConfigService.Current.ChannelOrder = new List<string>(_channelOrder);
_chatConfigService.Save();
updated = true;
}
if (updated)
{
PublishChannelListChanged();
}
}
public Task SetChatEnabledAsync(bool enabled)
=> enabled ? EnableChatAsync() : DisableChatAsync();
@@ -512,7 +550,7 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
if (!_isLoggedIn || !_apiController.IsConnected)
{
await LeaveCurrentZoneAsync(force, 0).ConfigureAwait(false);
await LeaveCurrentZoneAsync(force, 0, 0).ConfigureAwait(false);
return;
}
@@ -520,6 +558,7 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
{
var location = await _dalamudUtilService.GetMapDataAsync().ConfigureAwait(false);
var territoryId = (ushort)location.TerritoryId;
var worldId = (ushort)location.ServerId;
string? zoneKey;
ZoneChannelDefinition? definition = null;
@@ -536,14 +575,14 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
if (definition is null)
{
await LeaveCurrentZoneAsync(force, territoryId).ConfigureAwait(false);
await LeaveCurrentZoneAsync(force, territoryId, worldId).ConfigureAwait(false);
return;
}
var descriptor = await BuildZoneDescriptorAsync(definition.Value).ConfigureAwait(false);
if (descriptor is null)
{
await LeaveCurrentZoneAsync(force, territoryId).ConfigureAwait(false);
await LeaveCurrentZoneAsync(force, territoryId, worldId).ConfigureAwait(false);
return;
}
@@ -586,7 +625,7 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
}
}
private async Task LeaveCurrentZoneAsync(bool force, ushort territoryId)
private async Task LeaveCurrentZoneAsync(bool force, ushort territoryId, ushort worldId)
{
ChatChannelDescriptor? descriptor = null;
@@ -602,7 +641,27 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
state.StatusText = !_chatEnabled
? "Chat services disabled"
: (_isConnected ? ZoneUnavailableMessage : "Disconnected from chat server");
state.DisplayName = "Zone Chat";
if (territoryId != 0
&& _dalamudUtilService.TerritoryData.Value.TryGetValue(territoryId, out var territoryName)
&& !string.IsNullOrWhiteSpace(territoryName))
{
state.DisplayName = territoryName;
}
else
{
state.DisplayName = "Zone Chat";
}
if (worldId != 0)
{
state.Descriptor = new ChatChannelDescriptor
{
Type = ChatChannelType.Zone,
WorldId = worldId,
ZoneId = territoryId,
CustomKey = string.Empty
};
}
}
if (string.Equals(_activeChannelKey, ZoneChannelKey, StringComparison.Ordinal))
@@ -1092,17 +1151,50 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
{
_channelOrder.Clear();
if (_channels.ContainsKey(ZoneChannelKey))
var configuredOrder = _chatConfigService.Current.ChannelOrder;
if (configuredOrder.Count > 0)
{
_channelOrder.Add(ZoneChannelKey);
var seen = new HashSet<string>(StringComparer.Ordinal);
foreach (var key in configuredOrder)
{
if (_channels.ContainsKey(key) && seen.Add(key))
{
_channelOrder.Add(key);
}
}
var remaining = _channels.Values
.Where(state => !seen.Contains(state.Key))
.ToList();
if (remaining.Count > 0)
{
var zoneKeys = remaining
.Where(state => state.Type == ChatChannelType.Zone)
.Select(state => state.Key);
var groupKeys = remaining
.Where(state => state.Type == ChatChannelType.Group)
.OrderBy(state => state.DisplayName, StringComparer.OrdinalIgnoreCase)
.Select(state => state.Key);
_channelOrder.AddRange(zoneKeys);
_channelOrder.AddRange(groupKeys);
}
}
else
{
if (_channels.ContainsKey(ZoneChannelKey))
{
_channelOrder.Add(ZoneChannelKey);
}
var groups = _channels.Values
.Where(state => state.Type == ChatChannelType.Group)
.OrderBy(state => state.DisplayName, StringComparer.OrdinalIgnoreCase)
.Select(state => state.Key);
var groups = _channels.Values
.Where(state => state.Type == ChatChannelType.Group)
.OrderBy(state => state.DisplayName, StringComparer.OrdinalIgnoreCase)
.Select(state => state.Key);
_channelOrder.AddRange(groups);
_channelOrder.AddRange(groups);
}
if (_activeChannelKey is null && _channelOrder.Count > 0)
{