Added syncshell profile related items.

This commit is contained in:
CakeAndBanana
2025-10-10 06:42:59 +02:00
parent 46db5c87e0
commit 98c3a2c7f8
13 changed files with 91 additions and 42 deletions

View File

@@ -138,7 +138,7 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
{ {
if (_allClientPairs.TryGetValue(user, out var pair)) if (_allClientPairs.TryGetValue(user, out var pair))
{ {
Mediator.Publish(new ClearProfileDataMessage(pair.UserData)); Mediator.Publish(new ClearProfileUserDataMessage(pair.UserData));
pair.MarkOffline(); pair.MarkOffline();
} }
@@ -149,7 +149,7 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
{ {
if (!_allClientPairs.ContainsKey(dto.User)) throw new InvalidOperationException("No user found for " + dto); if (!_allClientPairs.ContainsKey(dto.User)) throw new InvalidOperationException("No user found for " + dto);
Mediator.Publish(new ClearProfileDataMessage(dto.User)); Mediator.Publish(new ClearProfileUserDataMessage(dto.User));
var pair = _allClientPairs[dto.User]; var pair = _allClientPairs[dto.User];
if (pair.HasCachedPlayer) if (pair.HasCachedPlayer)
@@ -254,7 +254,7 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
if (pair.UserPair.OtherPermissions.IsPaused() != dto.Permissions.IsPaused()) if (pair.UserPair.OtherPermissions.IsPaused() != dto.Permissions.IsPaused())
{ {
Mediator.Publish(new ClearProfileDataMessage(dto.User)); Mediator.Publish(new ClearProfileUserDataMessage(dto.User));
} }
pair.UserPair.OtherPermissions = dto.Permissions; pair.UserPair.OtherPermissions = dto.Permissions;
@@ -280,7 +280,7 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
if (pair.UserPair.OwnPermissions.IsPaused() != dto.Permissions.IsPaused()) if (pair.UserPair.OwnPermissions.IsPaused() != dto.Permissions.IsPaused())
{ {
Mediator.Publish(new ClearProfileDataMessage(dto.User)); Mediator.Publish(new ClearProfileUserDataMessage(dto.User));
} }
pair.UserPair.OwnPermissions = dto.Permissions; pair.UserPair.OwnPermissions = dto.Permissions;

View File

@@ -0,0 +1,6 @@
namespace LightlessSync.Services;
public record LightlessGroupProfileData(string Base64ProfilePicture, string Description, string Tags)
{
public Lazy<byte[]> ImageData { get; } = new Lazy<byte[]>(Convert.FromBase64String(Base64ProfilePicture));
}

View File

@@ -18,11 +18,14 @@ public class LightlessProfileManager : MediatorSubscriberBase
private const string _nsfw = "Profile not displayed - NSFW"; private const string _nsfw = "Profile not displayed - NSFW";
private readonly ApiController _apiController; private readonly ApiController _apiController;
private readonly LightlessConfigService _lightlessConfigService; private readonly LightlessConfigService _lightlessConfigService;
private readonly ConcurrentDictionary<UserData, LightlessProfileData> _lightlessProfiles = new(UserDataComparer.Instance); private readonly ConcurrentDictionary<UserData, LightlessUserProfileData> _lightlessUserProfiles = new(UserDataComparer.Instance);
private readonly ConcurrentDictionary<GroupData, LightlessGroupProfileData> _lightlessGroupProfiles = new(GroupDataComparer.Instance);
private readonly LightlessProfileData _defaultProfileData = new(IsFlagged: false, IsNSFW: false, _lightlessLogo, string.Empty, _noDescription); private readonly LightlessUserProfileData _defaultProfileUserData = new(IsFlagged: false, IsNSFW: false, _lightlessLogo, string.Empty, _noDescription);
private readonly LightlessProfileData _loadingProfileData = new(IsFlagged: false, IsNSFW: false, _lightlessLogoLoading, string.Empty, "Loading Data from server..."); private readonly LightlessUserProfileData _loadingProfileUserData = new(IsFlagged: false, IsNSFW: false, _lightlessLogoLoading, string.Empty, "Loading User Profile Data from server...");
private readonly LightlessProfileData _nsfwProfileData = new(IsFlagged: false, IsNSFW: false, _lightlessLogoNsfw, string.Empty, _nsfw); private readonly LightlessGroupProfileData _loadingProfileGroupData = new(_lightlessLogoLoading, "Loading Group Profile Data from server...", string.Empty);
private readonly LightlessGroupProfileData _defaultProfileGroupData = new(_lightlessLogo, _noDescription, string.Empty);
private readonly LightlessUserProfileData _nsfwProfileData = new(IsFlagged: false, IsNSFW: false, _lightlessLogoNsfw, string.Empty, _nsfw);
public LightlessProfileManager(ILogger<LightlessProfileManager> logger, LightlessConfigService lightlessConfigService, public LightlessProfileManager(ILogger<LightlessProfileManager> logger, LightlessConfigService lightlessConfigService,
LightlessMediator mediator, ApiController apiController) : base(logger, mediator) LightlessMediator mediator, ApiController apiController) : base(logger, mediator)
@@ -30,22 +33,33 @@ public class LightlessProfileManager : MediatorSubscriberBase
_lightlessConfigService = lightlessConfigService; _lightlessConfigService = lightlessConfigService;
_apiController = apiController; _apiController = apiController;
Mediator.Subscribe<ClearProfileDataMessage>(this, (msg) => Mediator.Subscribe<ClearProfileUserDataMessage>(this, (msg) =>
{ {
if (msg.UserData != null) if (msg.UserData != null)
_lightlessProfiles.Remove(msg.UserData, out _); _lightlessUserProfiles.Remove(msg.UserData, out _);
else else
_lightlessProfiles.Clear(); _lightlessUserProfiles.Clear();
}); });
Mediator.Subscribe<DisconnectedMessage>(this, (_) => _lightlessProfiles.Clear()); Mediator.Subscribe<DisconnectedMessage>(this, (_) => _lightlessUserProfiles.Clear());
} }
public LightlessProfileData GetLightlessProfile(UserData data) public LightlessUserProfileData GetLightlessUserProfile(UserData data)
{ {
if (!_lightlessProfiles.TryGetValue(data, out var profile)) if (!_lightlessUserProfiles.TryGetValue(data, out var profile))
{ {
_ = Task.Run(() => GetLightlessProfileFromService(data)); _ = Task.Run(() => GetLightlessProfileFromService(data));
return (_loadingProfileData); return (_loadingProfileUserData);
}
return (profile);
}
public LightlessGroupProfileData GetLightlessGroupProfile(GroupData data)
{
if (!_lightlessGroupProfiles.TryGetValue(data, out var profile))
{
_ = Task.Run(() => GetLightlessProfileFromService(data));
return (_loadingProfileGroupData);
} }
return (profile); return (profile);
@@ -55,26 +69,47 @@ public class LightlessProfileManager : MediatorSubscriberBase
{ {
try try
{ {
_lightlessProfiles[data] = _loadingProfileData; _lightlessUserProfiles[data] = _loadingProfileUserData;
var profile = await _apiController.UserGetProfile(new API.Dto.User.UserDto(data)).ConfigureAwait(false); var profile = await _apiController.UserGetProfile(new API.Dto.User.UserDto(data)).ConfigureAwait(false);
LightlessProfileData profileData = new(profile.Disabled, profile.IsNSFW ?? false, LightlessUserProfileData profileData = new(profile.Disabled, profile.IsNSFW ?? false,
string.IsNullOrEmpty(profile.ProfilePictureBase64) ? _lightlessLogo : profile.ProfilePictureBase64, string.IsNullOrEmpty(profile.ProfilePictureBase64) ? _lightlessLogo : profile.ProfilePictureBase64,
!string.IsNullOrEmpty(data.Alias) && !string.Equals(data.Alias, data.UID, StringComparison.Ordinal) ? _lightlessSupporter : string.Empty, !string.IsNullOrEmpty(data.Alias) && !string.Equals(data.Alias, data.UID, StringComparison.Ordinal) ? _lightlessSupporter : string.Empty,
string.IsNullOrEmpty(profile.Description) ? _noDescription : profile.Description); string.IsNullOrEmpty(profile.Description) ? _noDescription : profile.Description);
if (profileData.IsNSFW && !_lightlessConfigService.Current.ProfilesAllowNsfw && !string.Equals(_apiController.UID, data.UID, StringComparison.Ordinal)) if (profileData.IsNSFW && !_lightlessConfigService.Current.ProfilesAllowNsfw && !string.Equals(_apiController.UID, data.UID, StringComparison.Ordinal))
{ {
_lightlessProfiles[data] = _nsfwProfileData; _lightlessUserProfiles[data] = _nsfwProfileData;
} }
else else
{ {
_lightlessProfiles[data] = profileData; _lightlessUserProfiles[data] = profileData;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
// if fails save DefaultProfileData to dict // if fails save DefaultProfileData to dict
Logger.LogWarning(ex, "Failed to get Profile from service for user {user}", data); Logger.LogWarning(ex, "Failed to get Profile from service for user {user}", data);
_lightlessProfiles[data] = _defaultProfileData; _lightlessUserProfiles[data] = _defaultProfileUserData;
}
}
private async Task GetLightlessProfileFromService(GroupData data)
{
try
{
_lightlessGroupProfiles[data] = _loadingProfileGroupData;
var profile = await _apiController.GroupGetProfile(new API.Dto.Group.GroupDto(data)).ConfigureAwait(false);
LightlessGroupProfileData profileData = new(
string.IsNullOrEmpty(profile.PictureBase64) ? _lightlessLogo : profile.PictureBase64,
!string.IsNullOrEmpty(data.Alias) && !string.Equals(data.Alias, data.GID, StringComparison.Ordinal) ? _lightlessSupporter : string.Empty,
string.IsNullOrEmpty(profile.Description) ? _noDescription : profile.Description);
_lightlessGroupProfiles[data] = profileData;
}
catch (Exception ex)
{
// if fails save DefaultProfileData to dict
Logger.LogWarning(ex, "Failed to get Profile from service for group {group}", data);
_lightlessGroupProfiles[data] = _defaultProfileGroupData;
} }
} }
} }

View File

@@ -1,6 +1,6 @@
namespace LightlessSync.Services; namespace LightlessSync.Services;
public record LightlessProfileData(bool IsFlagged, bool IsNSFW, string Base64ProfilePicture, string Base64SupporterPicture, string Description) public record LightlessUserProfileData(bool IsFlagged, bool IsNSFW, string Base64ProfilePicture, string Base64SupporterPicture, string Description)
{ {
public Lazy<byte[]> ImageData { get; } = new Lazy<byte[]>(Convert.FromBase64String(Base64ProfilePicture)); public Lazy<byte[]> ImageData { get; } = new Lazy<byte[]>(Convert.FromBase64String(Base64ProfilePicture));
public Lazy<byte[]> SupporterImageData { get; } = new Lazy<byte[]>(string.IsNullOrEmpty(Base64SupporterPicture) ? [] : Convert.FromBase64String(Base64SupporterPicture)); public Lazy<byte[]> SupporterImageData { get; } = new Lazy<byte[]>(string.IsNullOrEmpty(Base64SupporterPicture) ? [] : Convert.FromBase64String(Base64SupporterPicture));

View File

@@ -64,7 +64,8 @@ public record DownloadStartedMessage(GameObjectHandler DownloadId, Dictionary<st
public record DownloadFinishedMessage(GameObjectHandler DownloadId) : MessageBase; public record DownloadFinishedMessage(GameObjectHandler DownloadId) : MessageBase;
public record UiToggleMessage(Type UiType) : MessageBase; public record UiToggleMessage(Type UiType) : MessageBase;
public record PlayerUploadingMessage(GameObjectHandler Handler, bool IsUploading) : MessageBase; public record PlayerUploadingMessage(GameObjectHandler Handler, bool IsUploading) : MessageBase;
public record ClearProfileDataMessage(UserData? UserData = null) : MessageBase; public record ClearProfileUserDataMessage(UserData? UserData = null) : MessageBase;
public record ClearProfileGroupDataMessage(GroupData? GroupData = null) : MessageBase;
public record CyclePauseMessage(UserData UserData) : MessageBase; public record CyclePauseMessage(UserData UserData) : MessageBase;
public record PauseMessage(UserData UserData) : MessageBase; public record PauseMessage(UserData UserData) : MessageBase;
public record ProfilePopoutToggle(Pair? Pair) : MessageBase; public record ProfilePopoutToggle(Pair? Pair) : MessageBase;

View File

@@ -36,7 +36,7 @@ public class UiFactory
public SyncshellAdminUI CreateSyncshellAdminUi(GroupFullInfoDto dto) public SyncshellAdminUI CreateSyncshellAdminUi(GroupFullInfoDto dto)
{ {
return new SyncshellAdminUI(_loggerFactory.CreateLogger<SyncshellAdminUI>(), _lightlessMediator, return new SyncshellAdminUI(_loggerFactory.CreateLogger<SyncshellAdminUI>(), _lightlessMediator,
_apiController, _uiSharedService, _pairManager, dto, _performanceCollectorService); _apiController, _uiSharedService, _pairManager, dto, _performanceCollectorService, _lightlessProfileManager);
} }
public StandaloneProfileUi CreateStandaloneProfileUi(Pair pair) public StandaloneProfileUi CreateStandaloneProfileUi(Pair pair)

View File

@@ -25,8 +25,8 @@ public class EditProfileUi : WindowMediatorSubscriberBase
private readonly FileDialogManager _fileDialogManager; private readonly FileDialogManager _fileDialogManager;
private readonly LightlessProfileManager _lightlessProfileManager; private readonly LightlessProfileManager _lightlessProfileManager;
private readonly UiSharedService _uiSharedService; private readonly UiSharedService _uiSharedService;
private bool _adjustedForScollBarsLocalProfile = false; private bool _adjustedForScollBarsLocalProfile = false;
private bool _adjustedForScollBarsOnlineProfile = false; private bool _adjustedForScollBarsOnlineProfile = false;
private string _descriptionText = string.Empty; private string _descriptionText = string.Empty;
private IDalamudTextureWrap? _pfpTextureWrap; private IDalamudTextureWrap? _pfpTextureWrap;
private string _profileDescription = string.Empty; private string _profileDescription = string.Empty;
@@ -63,7 +63,7 @@ public class EditProfileUi : WindowMediatorSubscriberBase
Mediator.Subscribe<GposeStartMessage>(this, (_) => { _wasOpen = IsOpen; IsOpen = false; }); Mediator.Subscribe<GposeStartMessage>(this, (_) => { _wasOpen = IsOpen; IsOpen = false; });
Mediator.Subscribe<GposeEndMessage>(this, (_) => IsOpen = _wasOpen); Mediator.Subscribe<GposeEndMessage>(this, (_) => IsOpen = _wasOpen);
Mediator.Subscribe<DisconnectedMessage>(this, (_) => IsOpen = false); Mediator.Subscribe<DisconnectedMessage>(this, (_) => IsOpen = false);
Mediator.Subscribe<ClearProfileDataMessage>(this, (msg) => Mediator.Subscribe<ClearProfileUserDataMessage>(this, (msg) =>
{ {
if (msg.UserData == null || string.Equals(msg.UserData.UID, _apiController.UID, StringComparison.Ordinal)) if (msg.UserData == null || string.Equals(msg.UserData.UID, _apiController.UID, StringComparison.Ordinal))
{ {
@@ -108,7 +108,7 @@ public class EditProfileUi : WindowMediatorSubscriberBase
ImGui.Dummy(new Vector2(3)); ImGui.Dummy(new Vector2(3));
var profile = _lightlessProfileManager.GetLightlessProfile(new UserData(_apiController.UID)); var profile = _lightlessProfileManager.GetLightlessUserProfile(new UserData(_apiController.UID));
if (ImGui.BeginTabBar("##EditProfileTabs")) if (ImGui.BeginTabBar("##EditProfileTabs"))
{ {

View File

@@ -85,7 +85,7 @@ public class PopoutProfileUi : WindowMediatorSubscriberBase
{ {
var spacing = ImGui.GetStyle().ItemSpacing; var spacing = ImGui.GetStyle().ItemSpacing;
var lightlessProfile = _lightlessProfileManager.GetLightlessProfile(_pair.UserData); var lightlessProfile = _lightlessProfileManager.GetLightlessUserProfile(_pair.UserData);
if (_textureWrap == null || !lightlessProfile.ImageData.Value.SequenceEqual(_lastProfilePicture)) if (_textureWrap == null || !lightlessProfile.ImageData.Value.SequenceEqual(_lastProfilePicture))
{ {

View File

@@ -1599,7 +1599,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
{ {
if (ImGui.Checkbox("Show Lightless Profiles on Hover", ref showProfiles)) if (ImGui.Checkbox("Show Lightless Profiles on Hover", ref showProfiles))
{ {
Mediator.Publish(new ClearProfileDataMessage()); Mediator.Publish(new ClearProfileUserDataMessage());
_configService.Current.ProfilesShow = showProfiles; _configService.Current.ProfilesShow = showProfiles;
_configService.Save(); _configService.Save();
} }
@@ -1623,7 +1623,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
ImGui.Unindent(); ImGui.Unindent();
if (ImGui.Checkbox("Show profiles marked as NSFW", ref showNsfwProfiles)) if (ImGui.Checkbox("Show profiles marked as NSFW", ref showNsfwProfiles))
{ {
Mediator.Publish(new ClearProfileDataMessage()); Mediator.Publish(new ClearProfileUserDataMessage());
_configService.Current.ProfilesAllowNsfw = showNsfwProfiles; _configService.Current.ProfilesAllowNsfw = showNsfwProfiles;
_configService.Save(); _configService.Save();
} }

View File

@@ -51,7 +51,7 @@ public class StandaloneProfileUi : WindowMediatorSubscriberBase
{ {
var spacing = ImGui.GetStyle().ItemSpacing; var spacing = ImGui.GetStyle().ItemSpacing;
var lightlessProfile = _lightlessProfileManager.GetLightlessProfile(Pair.UserData); var lightlessProfile = _lightlessProfileManager.GetLightlessUserProfile(Pair.UserData);
if (_textureWrap == null || !lightlessProfile.ImageData.Value.SequenceEqual(_lastProfilePicture)) if (_textureWrap == null || !lightlessProfile.ImageData.Value.SequenceEqual(_lastProfilePicture))
{ {

View File

@@ -192,7 +192,7 @@ public partial class ApiController
public Task Client_UserUpdateProfile(UserDto dto) public Task Client_UserUpdateProfile(UserDto dto)
{ {
Logger.LogDebug("Client_UserUpdateProfile: {dto}", dto); Logger.LogDebug("Client_UserUpdateProfile: {dto}", dto);
ExecuteSafely(() => Mediator.Publish(new ClearProfileDataMessage(dto.User))); ExecuteSafely(() => Mediator.Publish(new ClearProfileUserDataMessage(dto.User)));
return Task.CompletedTask; return Task.CompletedTask;
} }
@@ -377,6 +377,12 @@ public partial class ApiController
_lightlessHub!.On(nameof(Client_UserUpdateProfile), act); _lightlessHub!.On(nameof(Client_UserUpdateProfile), act);
} }
public void ClientGroupSendProfile(Action<GroupProfileDto> act)
{
if (_initialized) return;
_lightlessHub!.On(nameof(Client_GroupSendProfile), act);
}
public void OnUserUpdateSelfPairPermissions(Action<UserPermissionsDto> act) public void OnUserUpdateSelfPairPermissions(Action<UserPermissionsDto> act)
{ {
if (_initialized) return; if (_initialized) return;

View File

@@ -115,6 +115,17 @@ public partial class ApiController
CheckConnection(); CheckConnection();
return await _lightlessHub!.InvokeAsync<int>(nameof(GroupPrune), group, days, execute).ConfigureAwait(false); return await _lightlessHub!.InvokeAsync<int>(nameof(GroupPrune), group, days, execute).ConfigureAwait(false);
} }
public async Task<GroupProfileDto> GroupGetProfile(GroupDto dto)
{
if (!IsConnected) return new GroupProfileDto(Group: dto.Group, Description: null, Tags: null, PictureBase64: null);
return await _lightlessHub!.InvokeAsync<GroupProfileDto>(nameof(GroupGetProfile), dto).ConfigureAwait(false);
}
public async Task GroupSetProfile(GroupProfileDto dto)
{
if (!IsConnected) return;
await _lightlessHub!.InvokeAsync(nameof(GroupSetProfile), dto).ConfigureAwait(false);
}
public async Task<List<GroupFullInfoDto>> GroupsGetAll() public async Task<List<GroupFullInfoDto>> GroupsGetAll()
{ {

View File

@@ -610,15 +610,5 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IL
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<GroupProfileDto> GroupGetProfile(GroupDto dto)
{
throw new NotImplementedException();
}
public Task GroupSetProfile(GroupProfileDto dto)
{
throw new NotImplementedException();
}
} }
#pragma warning restore MA0040 #pragma warning restore MA0040