Compare commits
46 Commits
0.2.0.2
...
b4cad9c745
Author | SHA1 | Date | |
---|---|---|---|
b4cad9c745 | |||
100c5612dc | |||
b8e0100bdf | |||
137db42446
|
|||
956d2009eb | |||
ec66da8b5e | |||
0555ee0db7
|
|||
837b487281
|
|||
9a0f2c062c
|
|||
![]() |
6e9c69c2a8 | ||
f0cef81b5e | |||
d8160effd0
|
|||
18da07763c
|
|||
3c448f2290
|
|||
cadc7e223f | |||
e1baca7940 | |||
c2e0cf65a8 | |||
a3d0408d6f | |||
9ca6931bb8 | |||
f22eff1f72 | |||
11e097d696 | |||
f7ecb45774 | |||
00a7328e3a | |||
c39229a28b | |||
00c56b0888
|
|||
15898d54c2
|
|||
6d5ed42e60 | |||
92a8e224ef | |||
669ceed2a9
|
|||
778d30ae26 | |||
d2212da456
|
|||
a3dfe35df6
|
|||
da6623741c
|
|||
abea8f0856
|
|||
1624a84cf1 | |||
ba852831aa
|
|||
5de9ad3a54
|
|||
4c8ce23e8a
|
|||
2be5f5d320
|
|||
c428f306ca
|
|||
3dde713c91
|
|||
3280446c7e
|
|||
a408e22a68 | |||
1b71cda403 | |||
eb8dbbd7f9 | |||
abc361faf0
|
52
.gitea/workflows/build.yml
Normal file
52
.gitea/workflows/build.yml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
name: .NET Build and Publish to Gitea
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: dotnet
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- name: Restore dependencies
|
||||||
|
run: dotnet restore
|
||||||
|
|
||||||
|
- name: Download Dalamud
|
||||||
|
run: |
|
||||||
|
mkdir -p $HOME/.xlcore/dalamud/Hooks/dev/
|
||||||
|
curl -L https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -o latest.zip
|
||||||
|
unzip -o latest.zip -d $HOME/.xlcore/dalamud/Hooks/dev/
|
||||||
|
|
||||||
|
- name: Build project
|
||||||
|
run: dotnet build --no-restore --configuration Release --nologo
|
||||||
|
|
||||||
|
- name: Publish Windows executable
|
||||||
|
run: dotnet publish -c Release -r win-x64 --self-contained true -o ./publish
|
||||||
|
|
||||||
|
- name: Archive published files
|
||||||
|
run: zip -r SnowcloakClient.zip ./publish/*
|
||||||
|
|
||||||
|
- name: Create Gitea release
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.BUILD_SNOWCLOAK_CLIENT }}
|
||||||
|
run: |
|
||||||
|
API_URL="https://git.snowcloak-sync.com/api/v1/repos/Eauldane/SnowcloakClient/releases"
|
||||||
|
TAG="v$(date +%Y%m%d%H%M)"
|
||||||
|
# Create release
|
||||||
|
RELEASE_ID=$(curl -s -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
-d "{\"tag_name\":\"$TAG\",\"name\":\"Automated Build $TAG\",\"body\":\"Automated build artifact\"}" \
|
||||||
|
$API_URL | jq -r '.id')
|
||||||
|
echo "Release ID: $RELEASE_ID"
|
||||||
|
# Upload asset
|
||||||
|
curl -s -X POST \
|
||||||
|
-H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
-F "name=SnowcloakClient.zip" \
|
||||||
|
-F "attachment=@SnowcloakClient.zip" \
|
||||||
|
"$API_URL/$RELEASE_ID/assets"
|
@@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
.editorconfig = .editorconfig
|
.editorconfig = .editorconfig
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SnowcloakSync", "SnowcloakSync\SnowcloakSync.csproj", "{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -36,6 +38,14 @@ Global
|
|||||||
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|Any CPU.Build.0 = Release|Any CPU
|
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|x64.ActiveCfg = Release|Any CPU
|
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|x64.Build.0 = Release|Any CPU
|
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|x64.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@@ -27,9 +27,9 @@ public sealed class IpcCallerMoodles : IIpcCaller
|
|||||||
|
|
||||||
_moodlesApiVersion = pi.GetIpcSubscriber<int>("Moodles.Version");
|
_moodlesApiVersion = pi.GetIpcSubscriber<int>("Moodles.Version");
|
||||||
_moodlesOnChange = pi.GetIpcSubscriber<IPlayerCharacter, object>("Moodles.StatusManagerModified");
|
_moodlesOnChange = pi.GetIpcSubscriber<IPlayerCharacter, object>("Moodles.StatusManagerModified");
|
||||||
_moodlesGetStatus = pi.GetIpcSubscriber<nint, string>("Moodles.GetStatusManagerByPtr");
|
_moodlesGetStatus = pi.GetIpcSubscriber<nint, string>("Moodles.GetStatusManagerByPtrV2");
|
||||||
_moodlesSetStatus = pi.GetIpcSubscriber<nint, string, object>("Moodles.SetStatusManagerByPtr");
|
_moodlesSetStatus = pi.GetIpcSubscriber<nint, string, object>("Moodles.SetStatusManagerByPtrV2");
|
||||||
_moodlesRevertStatus = pi.GetIpcSubscriber<nint, object>("Moodles.ClearStatusManagerByPtr");
|
_moodlesRevertStatus = pi.GetIpcSubscriber<nint, object>("Moodles.ClearStatusManagerByPtrV2");
|
||||||
|
|
||||||
_moodlesOnChange.Subscribe(OnMoodlesChange);
|
_moodlesOnChange.Subscribe(OnMoodlesChange);
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ public sealed class IpcCallerMoodles : IIpcCaller
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
APIAvailable = _moodlesApiVersion.InvokeFunc() == 1;
|
APIAvailable = _moodlesApiVersion.InvokeFunc() == 3;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@@ -30,12 +30,12 @@ public sealed class IpcCallerPetNames : IIpcCaller
|
|||||||
_dalamudUtil = dalamudUtil;
|
_dalamudUtil = dalamudUtil;
|
||||||
_mareMediator = mareMediator;
|
_mareMediator = mareMediator;
|
||||||
|
|
||||||
_petnamesReady = pi.GetIpcSubscriber<object>("PetRenamer.Ready");
|
_petnamesReady = pi.GetIpcSubscriber<object>("PetRenamer.OnReady");
|
||||||
_petnamesDisposing = pi.GetIpcSubscriber<object>("PetRenamer.Disposing");
|
_petnamesDisposing = pi.GetIpcSubscriber<object>("PetRenamer.OnDisposing");
|
||||||
_apiVersion = pi.GetIpcSubscriber<(uint, uint)>("PetRenamer.ApiVersion");
|
_apiVersion = pi.GetIpcSubscriber<(uint, uint)>("PetRenamer.ApiVersion");
|
||||||
_enabled = pi.GetIpcSubscriber<bool>("PetRenamer.Enabled");
|
_enabled = pi.GetIpcSubscriber<bool>("PetRenamer.IsEnabled");
|
||||||
|
|
||||||
_playerDataChanged = pi.GetIpcSubscriber<string, object>("PetRenamer.PlayerDataChanged");
|
_playerDataChanged = pi.GetIpcSubscriber<string, object>("PetRenamer.OnPlayerDataChanged");
|
||||||
_getPlayerData = pi.GetIpcSubscriber<string>("PetRenamer.GetPlayerData");
|
_getPlayerData = pi.GetIpcSubscriber<string>("PetRenamer.GetPlayerData");
|
||||||
_setPlayerData = pi.GetIpcSubscriber<string, object>("PetRenamer.SetPlayerData");
|
_setPlayerData = pi.GetIpcSubscriber<string, object>("PetRenamer.SetPlayerData");
|
||||||
_clearPlayerData = pi.GetIpcSubscriber<ushort, object>("PetRenamer.ClearPlayerData");
|
_clearPlayerData = pi.GetIpcSubscriber<ushort, object>("PetRenamer.ClearPlayerData");
|
||||||
@@ -56,7 +56,7 @@ public sealed class IpcCallerPetNames : IIpcCaller
|
|||||||
APIAvailable = _enabled?.InvokeFunc() ?? false;
|
APIAvailable = _enabled?.InvokeFunc() ?? false;
|
||||||
if (APIAvailable)
|
if (APIAvailable)
|
||||||
{
|
{
|
||||||
APIAvailable = _apiVersion?.InvokeFunc() is { Item1: 3, Item2: >= 1 };
|
APIAvailable = _apiVersion?.InvokeFunc() is { Item1: 4, Item2: >= 0 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@@ -7,6 +7,7 @@ namespace MareSynchronos.MareConfiguration.Configurations;
|
|||||||
[Serializable]
|
[Serializable]
|
||||||
public class MareConfig : IMareConfiguration
|
public class MareConfig : IMareConfiguration
|
||||||
{
|
{
|
||||||
|
public bool SortSyncshellsByVRAM { get; set; } = false;
|
||||||
public int ExpectedTOSVersion = 2;
|
public int ExpectedTOSVersion = 2;
|
||||||
public int AcceptedTOSVersion { get; set; } = 0;
|
public int AcceptedTOSVersion { get; set; } = 0;
|
||||||
public bool AcceptedAgreement { get; set; } = false;
|
public bool AcceptedAgreement { get; set; } = false;
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Dalamud.NET.Sdk/13.0.0">
|
<Project Sdk="Dalamud.NET.Sdk/13.1.0">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AssemblyName>Snowcloak</AssemblyName>
|
<AssemblyName>Snowcloak</AssemblyName>
|
||||||
<Version>0.2.0.2</Version>
|
<Version>0.2.4</Version>
|
||||||
<PackageProjectUrl>https://github.com/Eauldane/SnowcloakClient/</PackageProjectUrl>
|
<PackageProjectUrl>https://git.snowcloak-sync.com/Eauldane/SnowcloakClient/</PackageProjectUrl>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -14,10 +14,12 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Chaos.NaCl.Standard" Version="1.0.0" />
|
<PackageReference Include="Chaos.NaCl.Standard" Version="1.0.0" />
|
||||||
<PackageReference Include="Downloader" Version="3.3.4" />
|
<PackageReference Include="Downloader" Version="4.0.3" />
|
||||||
<PackageReference Include="K4os.Compression.LZ4.Legacy" Version="1.3.8" />
|
<PackageReference Include="K4os.Compression.LZ4.Legacy" Version="1.3.8" />
|
||||||
<PackageReference Include="K4os.Compression.LZ4.Streams" Version="1.3.8" />
|
<PackageReference Include="K4os.Compression.LZ4.Streams" Version="1.3.8" />
|
||||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.212">
|
<PackageReference Include="MessagePack" Version="3.1.4" />
|
||||||
|
<PackageReference Include="MessagePack.Annotations" Version="3.1.4" />
|
||||||
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.213">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@@ -29,6 +31,8 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
|
||||||
|
<PackageReference Update="DalamudPackager" Version="13.1.0" />
|
||||||
|
<PackageReference Include="System.IO.Pipelines" Version="9.0.8" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="Exists('.\Penumbra.Api\Penumbra.Api.csproj')">
|
<ItemGroup Condition="Exists('.\Penumbra.Api\Penumbra.Api.csproj')">
|
||||||
@@ -54,6 +58,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MareAPI\MareSynchronosAPI\MareSynchronos.API.csproj" />
|
<ProjectReference Include="..\MareAPI\MareSynchronosAPI\MareSynchronos.API.csproj" />
|
||||||
|
<ProjectReference Include="..\SnowcloakSync\SnowcloakSync.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@@ -235,11 +235,17 @@ public class Pair : DisposableMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
string? noteOrName = GetNoteOrName();
|
string? noteOrName = GetNoteOrName();
|
||||||
|
|
||||||
if (noteOrName != null)
|
if (_mareConfig.Current.SortSyncshellsByVRAM)
|
||||||
|
{
|
||||||
|
return($"0{LastAppliedApproximateVRAMBytes}");
|
||||||
|
}
|
||||||
|
else if (noteOrName != null) {
|
||||||
return $"0{noteOrName}";
|
return $"0{noteOrName}";
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
return $"9{UserData.AliasOrUID}";
|
return $"9{UserData.AliasOrUID}";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string GetPlayerNameHash()
|
public string GetPlayerNameHash()
|
||||||
{
|
{
|
||||||
|
@@ -14,8 +14,9 @@ namespace MareSynchronos.Services;
|
|||||||
|
|
||||||
public sealed class CommandManagerService : IDisposable
|
public sealed class CommandManagerService : IDisposable
|
||||||
{
|
{
|
||||||
private const string _commandName = "/sync";
|
private const string _commandName = "/snow";
|
||||||
private const string _commandName2 = "/snowcloak";
|
private const string _commandName2 = "/snowcloak";
|
||||||
|
private const string _commandName3 = "/sync";
|
||||||
|
|
||||||
private const string _ssCommandPrefix = "/ss";
|
private const string _ssCommandPrefix = "/ss";
|
||||||
|
|
||||||
@@ -48,6 +49,10 @@ public sealed class CommandManagerService : IDisposable
|
|||||||
{
|
{
|
||||||
HelpMessage = "Opens the Snowcloak UI"
|
HelpMessage = "Opens the Snowcloak UI"
|
||||||
});
|
});
|
||||||
|
_commandManager.AddHandler(_commandName3, new CommandInfo(OnCommand)
|
||||||
|
{
|
||||||
|
HelpMessage = "Opens the Snowcloak UI"
|
||||||
|
});
|
||||||
|
|
||||||
// Lazy registration of all possible /ss# commands which tbf is what the game does for linkshells anyway
|
// Lazy registration of all possible /ss# commands which tbf is what the game does for linkshells anyway
|
||||||
for (int i = 1; i <= ChatService.CommandMaxNumber; ++i)
|
for (int i = 1; i <= ChatService.CommandMaxNumber; ++i)
|
||||||
|
@@ -9,6 +9,6 @@
|
|||||||
"customization"
|
"customization"
|
||||||
],
|
],
|
||||||
"IconUrl": "https://raw.githubusercontent.com/Eauldane/SnowcloakClient/refs/heads/main/MareSynchronos/images/logo.png",
|
"IconUrl": "https://raw.githubusercontent.com/Eauldane/SnowcloakClient/refs/heads/main/MareSynchronos/images/logo.png",
|
||||||
"RepoUrl": "https://github.com/Eauldane/SnowcloakClient",
|
"RepoUrl": "https://git.snowcloak-sync.com/Eauldane/SnowcloakClient",
|
||||||
"CanUnloadAsync": true
|
"CanUnloadAsync": true
|
||||||
}
|
}
|
||||||
|
@@ -1054,7 +1054,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
|
|||||||
_configService.Current.OpenMareHubOnGposeStart = openInGpose;
|
_configService.Current.OpenMareHubOnGposeStart = openInGpose;
|
||||||
_configService.Save();
|
_configService.Save();
|
||||||
}
|
}
|
||||||
_uiSharedService.DrawHelpText("This will automatically open the import menu when loading into Gpose. If unchecked you can open the menu manually with /sync gpose");
|
_uiSharedService.DrawHelpText("This will automatically open the import menu when loading into Gpose. If unchecked you can open the menu manually with /snow gpose");
|
||||||
bool downloadDataOnConnection = _configService.Current.DownloadMcdDataOnConnection;
|
bool downloadDataOnConnection = _configService.Current.DownloadMcdDataOnConnection;
|
||||||
if (ImGui.Checkbox("Download Online Character Data on connecting", ref downloadDataOnConnection))
|
if (ImGui.Checkbox("Download Online Character Data on connecting", ref downloadDataOnConnection))
|
||||||
{
|
{
|
||||||
|
@@ -105,7 +105,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
|||||||
protected override void DrawInternal()
|
protected override void DrawInternal()
|
||||||
{
|
{
|
||||||
if (_serverManager.CurrentApiUrl.Equals(ApiController.SnowcloakServiceUri, StringComparison.Ordinal))
|
if (_serverManager.CurrentApiUrl.Equals(ApiController.SnowcloakServiceUri, StringComparison.Ordinal))
|
||||||
UiSharedService.AccentColor = new(0.4275f, 0.6863f, 1f, 1f);
|
UiSharedService.AccentColor = SnowcloakSync.Utils.Colours._snowcloakOnline;
|
||||||
else
|
else
|
||||||
UiSharedService.AccentColor = ImGuiColors.ParsedGreen;
|
UiSharedService.AccentColor = ImGuiColors.ParsedGreen;
|
||||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ImGui.GetStyle().WindowPadding.Y - 1f * ImGuiHelpers.GlobalScale + ImGui.GetStyle().ItemSpacing.Y);
|
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ImGui.GetStyle().WindowPadding.Y - 1f * ImGuiHelpers.GlobalScale + ImGui.GetStyle().ItemSpacing.Y);
|
||||||
@@ -362,13 +362,14 @@ public class CompactUi : WindowMediatorSubscriberBase
|
|||||||
: (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - TransferPartHeight - ImGui.GetCursorPosY();
|
: (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - TransferPartHeight - ImGui.GetCursorPosY();
|
||||||
var users = GetFilteredUsers().OrderBy(u => u.GetPairSortKey(), StringComparer.Ordinal);
|
var users = GetFilteredUsers().OrderBy(u => u.GetPairSortKey(), StringComparer.Ordinal);
|
||||||
|
|
||||||
var onlineUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.IsOnline || u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Online" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
var onlineUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.IsOnline && !u.IsVisible && (!u.UserPair!.OtherPermissions.IsPaused() && !u.UserPair!.OwnPermissions.IsPaused()))).Select(c => new DrawUserPair("Online" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||||
|
var pausedUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.UserPair!.OtherPermissions.IsPaused() || u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Paused" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||||
var visibleUsers = users.Where(u => u.IsVisible).Select(c => new DrawUserPair("Visible" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
var visibleUsers = users.Where(u => u.IsVisible).Select(c => new DrawUserPair("Visible" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||||
var offlineUsers = users.Where(u => !u.UserPair!.OtherPermissions.IsPaired() || (!u.IsOnline && !u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Offline" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
var offlineUsers = users.Where(u => !u.UserPair!.OtherPermissions.IsPaired() || !u.IsOnline && (!u.UserPair!.OwnPermissions.IsPaused() && !u.UserPair.OtherPermissions.IsPaused())).Select(c => new DrawUserPair("Offline" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||||
|
|
||||||
ImGui.BeginChild("list", new Vector2(WindowContentWidth, ySize), border: false);
|
ImGui.BeginChild("list", new Vector2(WindowContentWidth, ySize), border: false);
|
||||||
|
|
||||||
_pairGroupsUi.Draw(visibleUsers, onlineUsers, offlineUsers);
|
_pairGroupsUi.Draw(visibleUsers, onlineUsers, pausedUsers, offlineUsers);
|
||||||
|
|
||||||
ImGui.EndChild();
|
ImGui.EndChild();
|
||||||
}
|
}
|
||||||
@@ -387,7 +388,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth()) / 2 - (userSize.X + textSize.X) / 2 - ImGui.GetStyle().ItemSpacing.X / 2);
|
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth()) / 2 - (userSize.X + textSize.X) / 2 - ImGui.GetStyle().ItemSpacing.X / 2);
|
||||||
if (!printShard) ImGui.AlignTextToFramePadding();
|
if (!printShard) ImGui.AlignTextToFramePadding();
|
||||||
ImGui.TextColored(ImGuiColors.ParsedGreen, userCount);
|
ImGui.TextColored(new Vector4(0.675f, 0.985f, 1f, 1f), userCount);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if (!printShard) ImGui.AlignTextToFramePadding();
|
if (!printShard) ImGui.AlignTextToFramePadding();
|
||||||
ImGui.TextUnformatted("Users Online");
|
ImGui.TextUnformatted("Users Online");
|
||||||
|
@@ -20,6 +20,7 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
private readonly GroupPairFullInfoDto _fullInfoDto;
|
private readonly GroupPairFullInfoDto _fullInfoDto;
|
||||||
private readonly GroupFullInfoDto _group;
|
private readonly GroupFullInfoDto _group;
|
||||||
private readonly CharaDataManager _charaDataManager;
|
private readonly CharaDataManager _charaDataManager;
|
||||||
|
public long VRAMUsage { get; set; }
|
||||||
|
|
||||||
public DrawGroupPair(string id, Pair entry, ApiController apiController,
|
public DrawGroupPair(string id, Pair entry, ApiController apiController,
|
||||||
MareMediator mareMediator, GroupFullInfoDto group, GroupPairFullInfoDto fullInfoDto,
|
MareMediator mareMediator, GroupFullInfoDto group, GroupPairFullInfoDto fullInfoDto,
|
||||||
@@ -80,6 +81,7 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
}
|
}
|
||||||
if (_pair.LastAppliedDataBytes >= 0)
|
if (_pair.LastAppliedDataBytes >= 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
presenceText += UiSharedService.TooltipSeparator;
|
presenceText += UiSharedService.TooltipSeparator;
|
||||||
presenceText += ((!_pair.IsVisible) ? "(Last) " : string.Empty) + "Mods Info" + Environment.NewLine;
|
presenceText += ((!_pair.IsVisible) ? "(Last) " : string.Empty) + "Mods Info" + Environment.NewLine;
|
||||||
presenceText += "Files Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataBytes, true);
|
presenceText += "Files Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataBytes, true);
|
||||||
@@ -127,6 +129,9 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
|
|
||||||
protected override float DrawRightSide(float textPosY, float originalY)
|
protected override float DrawRightSide(float textPosY, float originalY)
|
||||||
{
|
{
|
||||||
|
var pauseIcon = _pair.IsPaused ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
|
||||||
|
var pauseIconSize = _uiSharedService.GetIconButtonSize(pauseIcon);
|
||||||
|
var spacingX = ImGui.GetStyle().ItemSpacing.X;
|
||||||
var entryUID = _fullInfoDto.UserAliasOrUID;
|
var entryUID = _fullInfoDto.UserAliasOrUID;
|
||||||
var entryIsMod = _fullInfoDto.GroupPairStatusInfo.IsModerator();
|
var entryIsMod = _fullInfoDto.GroupPairStatusInfo.IsModerator();
|
||||||
var entryIsOwner = string.Equals(_pair.UserData.UID, _group.OwnerUID, StringComparison.Ordinal);
|
var entryIsOwner = string.Equals(_pair.UserData.UID, _group.OwnerUID, StringComparison.Ordinal);
|
||||||
@@ -145,19 +150,27 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
bool showInfo = (individualAnimDisabled || individualSoundsDisabled || animDisabled || soundsDisabled);
|
bool showInfo = (individualAnimDisabled || individualSoundsDisabled || animDisabled || soundsDisabled);
|
||||||
bool showPlus = _pair.UserPair == null;
|
bool showPlus = _pair.UserPair == null;
|
||||||
bool showBars = (userIsOwner || (userIsModerator && !entryIsMod && !entryIsOwner)) || !_pair.IsPaused;
|
bool showBars = (userIsOwner || (userIsModerator && !entryIsMod && !entryIsOwner)) || !_pair.IsPaused;
|
||||||
|
bool showPause = true;
|
||||||
var spacing = ImGui.GetStyle().ItemSpacing.X;
|
var spacing = ImGui.GetStyle().ItemSpacing.X;
|
||||||
var permIcon = (individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled) ? FontAwesomeIcon.ExclamationTriangle
|
var permIcon = (individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled) ? FontAwesomeIcon.ExclamationTriangle
|
||||||
: ((soundsDisabled || animDisabled || vfxDisabled) ? FontAwesomeIcon.InfoCircle : FontAwesomeIcon.None);
|
: ((soundsDisabled || animDisabled || vfxDisabled) ? FontAwesomeIcon.InfoCircle : FontAwesomeIcon.None);
|
||||||
var runningIconWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Running).X;
|
var runningIconWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Running).X;
|
||||||
var infoIconWidth = UiSharedService.GetIconSize(permIcon).X;
|
var infoIconWidth = UiSharedService.GetIconSize(permIcon).X;
|
||||||
var plusButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Plus).X;
|
var plusButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Plus).X;
|
||||||
|
var pauseButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Plus).X;
|
||||||
|
|
||||||
var barButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars).X;
|
var barButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars).X;
|
||||||
|
var barButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars);
|
||||||
|
|
||||||
|
var windowEndX = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth();
|
||||||
|
var rightSidePos = windowEndX - barButtonSize.X;
|
||||||
|
|
||||||
|
|
||||||
var pos = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() + spacing
|
var pos = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() + spacing
|
||||||
- (showShared ? (runningIconWidth + spacing) : 0)
|
- (showShared ? (runningIconWidth + spacing) : 0)
|
||||||
- (showInfo ? (infoIconWidth + spacing) : 0)
|
- (showInfo ? (infoIconWidth + spacing) : 0)
|
||||||
- (showPlus ? (plusButtonWidth + spacing) : 0)
|
- (showPlus ? (plusButtonWidth + spacing) : 0)
|
||||||
|
- (showPause ? (pauseButtonWidth + spacing) : 0)
|
||||||
- (showBars ? (barButtonWidth + spacing) : 0);
|
- (showBars ? (barButtonWidth + spacing) : 0);
|
||||||
|
|
||||||
ImGui.SameLine(pos);
|
ImGui.SameLine(pos);
|
||||||
@@ -264,6 +277,7 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (showPlus)
|
if (showPlus)
|
||||||
{
|
{
|
||||||
ImGui.SetCursorPosY(originalY);
|
ImGui.SetCursorPosY(originalY);
|
||||||
@@ -275,7 +289,25 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
UiSharedService.AttachToolTip("Pair with " + entryUID + " individually");
|
UiSharedService.AttachToolTip("Pair with " + entryUID + " individually");
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
}
|
}
|
||||||
|
if (showPause)
|
||||||
|
{
|
||||||
|
//rightSidePos -= pauseIconSize.X + spacingX;
|
||||||
|
ImGui.SetCursorPosY(originalY);
|
||||||
|
|
||||||
|
if (_uiSharedService.IconButton(pauseIcon))
|
||||||
|
{
|
||||||
|
var perm = _pair.UserPair!.OwnPermissions;
|
||||||
|
perm.SetPaused(!perm.IsPaused());
|
||||||
|
_ = _apiController.UserSetPairPermissions(new(_pair.UserData, perm));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
UiSharedService.AttachToolTip(!_fullInfoDto.GroupUserPermissions.IsPaused()
|
||||||
|
? "Pause pairing with " + entryUID
|
||||||
|
: "Resume pairing with " + entryUID);
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
}
|
||||||
if (showBars)
|
if (showBars)
|
||||||
{
|
{
|
||||||
ImGui.SetCursorPosY(originalY);
|
ImGui.SetCursorPosY(originalY);
|
||||||
@@ -285,7 +317,6 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
ImGui.OpenPopup("Popup");
|
ImGui.OpenPopup("Popup");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.BeginPopup("Popup"))
|
if (ImGui.BeginPopup("Popup"))
|
||||||
{
|
{
|
||||||
if ((userIsModerator || userIsOwner) && !(entryIsMod || entryIsOwner))
|
if ((userIsModerator || userIsOwner) && !(entryIsMod || entryIsOwner))
|
||||||
|
@@ -19,6 +19,7 @@ public class DrawUserPair : DrawPairBase
|
|||||||
protected readonly MareMediator _mediator;
|
protected readonly MareMediator _mediator;
|
||||||
private readonly SelectGroupForPairUi _selectGroupForPairUi;
|
private readonly SelectGroupForPairUi _selectGroupForPairUi;
|
||||||
private readonly CharaDataManager _charaDataManager;
|
private readonly CharaDataManager _charaDataManager;
|
||||||
|
public long VramUsage { get; set; }
|
||||||
|
|
||||||
public DrawUserPair(string id, Pair entry, UidDisplayHandler displayHandler, ApiController apiController,
|
public DrawUserPair(string id, Pair entry, UidDisplayHandler displayHandler, ApiController apiController,
|
||||||
MareMediator mareMediator, SelectGroupForPairUi selectGroupForPairUi,
|
MareMediator mareMediator, SelectGroupForPairUi selectGroupForPairUi,
|
||||||
@@ -51,26 +52,27 @@ public class DrawUserPair : DrawPairBase
|
|||||||
{
|
{
|
||||||
connectionIcon = FontAwesomeIcon.PauseCircle;
|
connectionIcon = FontAwesomeIcon.PauseCircle;
|
||||||
connectionText = "Pairing status with " + _pair.UserData.AliasOrUID + " is paused";
|
connectionText = "Pairing status with " + _pair.UserData.AliasOrUID + " is paused";
|
||||||
connectionColor = ImGuiColors.DalamudYellow;
|
connectionColor = ImGuiColors.DalamudGrey;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
connectionIcon = FontAwesomeIcon.Check;
|
connectionIcon = FontAwesomeIcon.Snowflake;
|
||||||
connectionText = "You are paired with " + _pair.UserData.AliasOrUID;
|
connectionText = "You are paired with " + _pair.UserData.AliasOrUID;
|
||||||
connectionColor = ImGuiColors.ParsedGreen;
|
connectionColor = _pair.IsOnline ? SnowcloakSync.Utils.Colours._snowcloakOnline : ImGuiColors.DalamudGrey;
|
||||||
}
|
}
|
||||||
|
if (!_pair.IsVisible)
|
||||||
ImGui.SetCursorPosY(textPosY);
|
|
||||||
ImGui.PushFont(UiBuilder.IconFont);
|
|
||||||
UiSharedService.ColorText(connectionIcon.ToIconString(), connectionColor);
|
|
||||||
ImGui.PopFont();
|
|
||||||
UiSharedService.AttachToolTip(connectionText);
|
|
||||||
if (_pair is { IsOnline: true, IsVisible: true })
|
|
||||||
{
|
{
|
||||||
ImGui.SameLine();
|
|
||||||
ImGui.SetCursorPosY(textPosY);
|
ImGui.SetCursorPosY(textPosY);
|
||||||
ImGui.PushFont(UiBuilder.IconFont);
|
ImGui.PushFont(UiBuilder.IconFont);
|
||||||
UiSharedService.ColorText(FontAwesomeIcon.Eye.ToIconString(), ImGuiColors.ParsedGreen);
|
UiSharedService.ColorText(connectionIcon.ToIconString(), connectionColor);
|
||||||
|
ImGui.PopFont();
|
||||||
|
UiSharedService.AttachToolTip(connectionText);
|
||||||
|
}
|
||||||
|
if (_pair is { IsOnline: true, IsVisible: true })
|
||||||
|
{
|
||||||
|
ImGui.SetCursorPosY(textPosY);
|
||||||
|
ImGui.PushFont(UiBuilder.IconFont);
|
||||||
|
UiSharedService.ColorText(FontAwesomeIcon.Eye.ToIconString(), SnowcloakSync.Utils.Colours._snowcloakOnline);
|
||||||
if (ImGui.IsItemClicked())
|
if (ImGui.IsItemClicked())
|
||||||
{
|
{
|
||||||
_mediator.Publish(new TargetPairMessage(_pair));
|
_mediator.Publish(new TargetPairMessage(_pair));
|
||||||
@@ -84,6 +86,7 @@ public class DrawUserPair : DrawPairBase
|
|||||||
visibleTooltip += "Files Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataBytes, true);
|
visibleTooltip += "Files Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataBytes, true);
|
||||||
if (_pair.LastAppliedApproximateVRAMBytes >= 0)
|
if (_pair.LastAppliedApproximateVRAMBytes >= 0)
|
||||||
{
|
{
|
||||||
|
VramUsage = _pair.LastAppliedApproximateVRAMBytes;
|
||||||
visibleTooltip += Environment.NewLine + "Approx. VRAM Usage: " + UiSharedService.ByteToString(_pair.LastAppliedApproximateVRAMBytes, true);
|
visibleTooltip += Environment.NewLine + "Approx. VRAM Usage: " + UiSharedService.ByteToString(_pair.LastAppliedApproximateVRAMBytes, true);
|
||||||
}
|
}
|
||||||
if (_pair.LastAppliedDataTris >= 0)
|
if (_pair.LastAppliedDataTris >= 0)
|
||||||
@@ -97,6 +100,8 @@ public class DrawUserPair : DrawPairBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected override float DrawRightSide(float textPosY, float originalY)
|
protected override float DrawRightSide(float textPosY, float originalY)
|
||||||
{
|
{
|
||||||
var pauseIcon = _pair.UserPair!.OwnPermissions.IsPaused() ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
|
var pauseIcon = _pair.UserPair!.OwnPermissions.IsPaused() ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
|
||||||
|
@@ -418,21 +418,34 @@ internal sealed class GroupPanel
|
|||||||
ImGui.Indent(20);
|
ImGui.Indent(20);
|
||||||
if (_expandedGroupState[groupDto.GID])
|
if (_expandedGroupState[groupDto.GID])
|
||||||
{
|
{
|
||||||
var sortedPairs = pairsInGroup
|
IOrderedEnumerable<Pair> sortedPairs;
|
||||||
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
|
if (!_mareConfig.Current.SortSyncshellsByVRAM)
|
||||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
|
{
|
||||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
|
sortedPairs = pairsInGroup
|
||||||
.ThenBy(u => u.GetPairSortKey(), StringComparer.OrdinalIgnoreCase);
|
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
|
||||||
|
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
|
||||||
|
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
|
||||||
|
.ThenBy(u => u.GetPairSortKey(), StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sortedPairs = pairsInGroup
|
||||||
|
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
|
||||||
|
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
|
||||||
|
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
|
||||||
|
.ThenByDescending(u => u.LastAppliedApproximateVRAMBytes);
|
||||||
|
}
|
||||||
|
|
||||||
var visibleUsers = new List<DrawGroupPair>();
|
var visibleUsers = new List<DrawGroupPair>();
|
||||||
var onlineUsers = new List<DrawGroupPair>();
|
var onlineUsers = new List<DrawGroupPair>();
|
||||||
var offlineUsers = new List<DrawGroupPair>();
|
var offlineUsers = new List<DrawGroupPair>();
|
||||||
|
|
||||||
|
|
||||||
foreach (var pair in sortedPairs)
|
foreach (var pair in sortedPairs)
|
||||||
{
|
{
|
||||||
var drawPair = new DrawGroupPair(
|
var drawPair = new DrawGroupPair(
|
||||||
groupDto.GID + pair.UserData.UID, pair,
|
groupDto.GID + pair.UserData.UID, pair,
|
||||||
ApiController, _mainUi.Mediator, groupDto,
|
ApiController, _mainUi.Mediator, groupDto,
|
||||||
pair.GroupPair.Single(
|
pair.GroupPair.Single(
|
||||||
g => GroupDataComparer.Instance.Equals(g.Key.Group, groupDto.Group)
|
g => GroupDataComparer.Instance.Equals(g.Key.Group, groupDto.Group)
|
||||||
).Value,
|
).Value,
|
||||||
@@ -453,6 +466,8 @@ internal sealed class GroupPanel
|
|||||||
ImGui.TextUnformatted("Visible");
|
ImGui.TextUnformatted("Visible");
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
_uidDisplayHandler.RenderPairList(visibleUsers);
|
_uidDisplayHandler.RenderPairList(visibleUsers);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onlineUsers.Count > 0)
|
if (onlineUsers.Count > 0)
|
||||||
|
@@ -28,15 +28,15 @@ public class PairGroupsUi
|
|||||||
_uiSharedService = uiSharedService;
|
_uiSharedService = uiSharedService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw<T>(List<T> visibleUsers, List<T> onlineUsers, List<T> offlineUsers) where T : DrawPairBase
|
public void Draw<T>(List<T> visibleUsers, List<T> onlineUsers, List<T> pausedUsers, List<T> offlineUsers) where T : DrawPairBase
|
||||||
{
|
{
|
||||||
// Only render those tags that actually have pairs in them, otherwise
|
// Only render those tags that actually have pairs in them, otherwise
|
||||||
// we can end up with a bunch of useless pair groups
|
// we can end up with a bunch of useless pair groups
|
||||||
var tagsWithPairsInThem = _tagHandler.GetAllTagsSorted();
|
var tagsWithPairsInThem = _tagHandler.GetAllTagsSorted();
|
||||||
var allUsers = onlineUsers.Concat(offlineUsers).ToList();
|
var allUsers = onlineUsers.Concat(offlineUsers).Concat(pausedUsers).ToList();
|
||||||
if (typeof(T) == typeof(DrawUserPair))
|
if (typeof(T) == typeof(DrawUserPair))
|
||||||
{
|
{
|
||||||
DrawUserPairs(tagsWithPairsInThem, allUsers.Cast<DrawUserPair>().ToList(), visibleUsers.Cast<DrawUserPair>(), onlineUsers.Cast<DrawUserPair>(), offlineUsers.Cast<DrawUserPair>());
|
DrawUserPairs(tagsWithPairsInThem, allUsers.Cast<DrawUserPair>().ToList(), visibleUsers.Cast<DrawUserPair>(), onlineUsers.Cast<DrawUserPair>(), pausedUsers.Cast<DrawUserPair>(), offlineUsers.Cast<DrawUserPair>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,13 +91,19 @@ public class PairGroupsUi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawCategory(string tag, IEnumerable<DrawPairBase> onlineUsers, IEnumerable<DrawPairBase> allUsers, IEnumerable<DrawPairBase>? visibleUsers = null)
|
private void DrawCategory(string tag, IEnumerable<DrawPairBase> onlineUsers, IEnumerable<DrawPairBase> pausedUsers, IEnumerable<DrawPairBase> allUsers, IEnumerable<DrawPairBase>? visibleUsers = null)
|
||||||
{
|
{
|
||||||
IEnumerable<DrawPairBase> usersInThisTag;
|
IEnumerable<DrawPairBase> usersInThisTag;
|
||||||
HashSet<string>? otherUidsTaggedWithTag = null;
|
HashSet<string>? otherUidsTaggedWithTag = null;
|
||||||
bool isSpecialTag = false;
|
bool isSpecialTag = false;
|
||||||
int visibleInThisTag = 0;
|
int visibleInThisTag = 0;
|
||||||
if (tag is TagHandler.CustomOfflineTag or TagHandler.CustomOnlineTag or TagHandler.CustomVisibleTag or TagHandler.CustomUnpairedTag)
|
|
||||||
|
if (tag is TagHandler.CustomPausedTag)
|
||||||
|
{
|
||||||
|
usersInThisTag = pausedUsers;
|
||||||
|
isSpecialTag = true;
|
||||||
|
}
|
||||||
|
else if (tag is TagHandler.CustomOfflineTag or TagHandler.CustomOnlineTag or TagHandler.CustomVisibleTag or TagHandler.CustomUnpairedTag)
|
||||||
{
|
{
|
||||||
usersInThisTag = onlineUsers;
|
usersInThisTag = onlineUsers;
|
||||||
isSpecialTag = true;
|
isSpecialTag = true;
|
||||||
@@ -113,14 +119,13 @@ public class PairGroupsUi
|
|||||||
|
|
||||||
if (isSpecialTag && !usersInThisTag.Any()) return;
|
if (isSpecialTag && !usersInThisTag.Any()) return;
|
||||||
|
|
||||||
DrawName(tag, isSpecialTag, visibleInThisTag, usersInThisTag.Count(), otherUidsTaggedWithTag?.Count);
|
DrawName(tag, isSpecialTag, visibleInThisTag, usersInThisTag.Count(), pausedUsers.Count(), otherUidsTaggedWithTag?.Count);
|
||||||
if (!isSpecialTag)
|
if (!isSpecialTag)
|
||||||
{
|
{
|
||||||
using (ImRaii.PushId($"group-{tag}-buttons")) DrawButtons(tag, allUsers.Cast<DrawUserPair>().Where(p => otherUidsTaggedWithTag!.Contains(p.UID)).ToList());
|
using (ImRaii.PushId($"group-{tag}-buttons")) DrawButtons(tag, allUsers.Cast<DrawUserPair>().Where(p => otherUidsTaggedWithTag!.Contains(p.UID)).ToList());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Avoid uncomfortably close group names
|
|
||||||
if (!_tagHandler.IsTagOpen(tag))
|
if (!_tagHandler.IsTagOpen(tag))
|
||||||
{
|
{
|
||||||
var size = ImGui.CalcTextSize("").Y + ImGui.GetStyle().FramePadding.Y * 2f;
|
var size = ImGui.CalcTextSize("").Y + ImGui.GetStyle().FramePadding.Y * 2f;
|
||||||
@@ -151,18 +156,19 @@ public class PairGroupsUi
|
|||||||
UiSharedService.AttachToolTip($"Delete Group {tag} (Will not delete the pairs)" + Environment.NewLine + "Hold CTRL to delete");
|
UiSharedService.AttachToolTip($"Delete Group {tag} (Will not delete the pairs)" + Environment.NewLine + "Hold CTRL to delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawName(string tag, bool isSpecialTag, int visible, int online, int? total)
|
private void DrawName(string tag, bool isSpecialTag, int visible, int online, int paused, int? total)
|
||||||
{
|
{
|
||||||
string displayedName = tag switch
|
string displayedName = tag switch
|
||||||
{
|
{
|
||||||
TagHandler.CustomUnpairedTag => "Unpaired",
|
TagHandler.CustomUnpairedTag => "Unpaired",
|
||||||
TagHandler.CustomOfflineTag => "Offline",
|
TagHandler.CustomOfflineTag => "Offline",
|
||||||
TagHandler.CustomOnlineTag => _mareConfig.Current.ShowOfflineUsersSeparately ? "Online/Paused" : "Contacts",
|
TagHandler.CustomOnlineTag => _mareConfig.Current.ShowOfflineUsersSeparately ? "Online" : "Contacts",
|
||||||
|
TagHandler.CustomPausedTag => "Paused",
|
||||||
TagHandler.CustomVisibleTag => "Visible",
|
TagHandler.CustomVisibleTag => "Visible",
|
||||||
_ => tag
|
_ => tag
|
||||||
};
|
};
|
||||||
|
|
||||||
string resultFolderName = !isSpecialTag ? $"{displayedName} ({visible}/{online}/{total} Pairs)" : $"{displayedName} ({online} Pairs)";
|
string resultFolderName = !isSpecialTag ? $"{displayedName} ({visible}/{online}/{paused}/{total} Pairs)" : $"{displayedName} ({online} Pairs)";
|
||||||
|
|
||||||
// FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight
|
// FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight
|
||||||
var icon = _tagHandler.IsTagOpen(tag) ? FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight;
|
var icon = _tagHandler.IsTagOpen(tag) ? FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight;
|
||||||
@@ -184,7 +190,8 @@ public class PairGroupsUi
|
|||||||
ImGui.TextUnformatted($"Group {tag}");
|
ImGui.TextUnformatted($"Group {tag}");
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
ImGui.TextUnformatted($"{visible} Pairs visible");
|
ImGui.TextUnformatted($"{visible} Pairs visible");
|
||||||
ImGui.TextUnformatted($"{online} Pairs online/paused");
|
ImGui.TextUnformatted($"{online} Pairs online");
|
||||||
|
ImGui.TextUnformatted($"{paused} Pairs paused");
|
||||||
ImGui.TextUnformatted($"{total} Pairs total");
|
ImGui.TextUnformatted($"{total} Pairs total");
|
||||||
ImGui.EndTooltip();
|
ImGui.EndTooltip();
|
||||||
}
|
}
|
||||||
@@ -197,39 +204,45 @@ public class PairGroupsUi
|
|||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawUserPairs(List<string> tagsWithPairsInThem, List<DrawUserPair> allUsers, IEnumerable<DrawUserPair> visibleUsers, IEnumerable<DrawUserPair> onlineUsers, IEnumerable<DrawUserPair> offlineUsers)
|
private void DrawUserPairs(List<string> tagsWithPairsInThem, List<DrawUserPair> allUsers, IEnumerable<DrawUserPair> visibleUsers, IEnumerable<DrawUserPair> onlineUsers, IEnumerable<DrawUserPair> pausedUsers, IEnumerable<DrawUserPair> offlineUsers)
|
||||||
{
|
{
|
||||||
if (_mareConfig.Current.ShowVisibleUsersSeparately)
|
if (_mareConfig.Current.ShowVisibleUsersSeparately)
|
||||||
{
|
{
|
||||||
using (ImRaii.PushId("$group-VisibleCustomTag")) DrawCategory(TagHandler.CustomVisibleTag, visibleUsers, allUsers);
|
using (ImRaii.PushId("$group-VisibleCustomTag")) DrawCategory(TagHandler.CustomVisibleTag, visibleUsers, Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var tag in tagsWithPairsInThem)
|
foreach (var tag in tagsWithPairsInThem)
|
||||||
{
|
{
|
||||||
if (_mareConfig.Current.ShowOfflineUsersSeparately)
|
if (_mareConfig.Current.ShowOfflineUsersSeparately)
|
||||||
{
|
{
|
||||||
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, onlineUsers, allUsers, visibleUsers);
|
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, onlineUsers, pausedUsers, allUsers, visibleUsers);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, allUsers, allUsers, visibleUsers);
|
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, allUsers, Enumerable.Empty<DrawUserPair>(), allUsers, visibleUsers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mareConfig.Current.ShowOfflineUsersSeparately)
|
if (_mareConfig.Current.ShowOfflineUsersSeparately)
|
||||||
{
|
{
|
||||||
using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag,
|
using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag,
|
||||||
onlineUsers.Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), allUsers);
|
onlineUsers.Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||||
|
if (pausedUsers.Any()) using (ImRaii.PushId("group-PausedCustomTag")) DrawCategory(TagHandler.CustomPausedTag,
|
||||||
|
Enumerable.Empty<DrawUserPair>(), pausedUsers, allUsers);
|
||||||
using (ImRaii.PushId($"group-OfflineCustomTag")) DrawCategory(TagHandler.CustomOfflineTag,
|
using (ImRaii.PushId($"group-OfflineCustomTag")) DrawCategory(TagHandler.CustomOfflineTag,
|
||||||
offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired()).ToList(), allUsers);
|
offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired()).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag,
|
using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag,
|
||||||
onlineUsers.Concat(offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired())).Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), allUsers);
|
onlineUsers.Concat(offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired())).Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||||
}
|
}
|
||||||
|
|
||||||
using (ImRaii.PushId($"group-UnpairedCustomTag")) DrawCategory(TagHandler.CustomUnpairedTag,
|
using (ImRaii.PushId($"group-UnpairedCustomTag")) DrawCategory(TagHandler.CustomUnpairedTag,
|
||||||
offlineUsers.Where(u => !u.UserPair!.OtherPermissions.IsPaired()).ToList(), allUsers);
|
offlineUsers.Where(u => !u.UserPair!.OtherPermissions.IsPaired()).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void PauseRemainingPairs(List<DrawUserPair> availablePairs)
|
private void PauseRemainingPairs(List<DrawUserPair> availablePairs)
|
||||||
{
|
{
|
||||||
foreach (var pairToPause in availablePairs.Where(pair => !pair.UserPair!.OwnPermissions.IsPaused()))
|
foreach (var pairToPause in availablePairs.Where(pair => !pair.UserPair!.OwnPermissions.IsPaused()))
|
||||||
|
@@ -203,10 +203,10 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
|||||||
DtrStyle.Style4 => $"\xE03A {text}",
|
DtrStyle.Style4 => $"\xE03A {text}",
|
||||||
DtrStyle.Style5 => $"\xE033 {text}",
|
DtrStyle.Style5 => $"\xE033 {text}",
|
||||||
DtrStyle.Style6 => $"\xE038 {text}",
|
DtrStyle.Style6 => $"\xE038 {text}",
|
||||||
DtrStyle.Style7 => $"\xE05D {text}",
|
DtrStyle.Style7 => $"\xE044 {text}",
|
||||||
DtrStyle.Style8 => $"\xE03C{text}",
|
DtrStyle.Style8 => $"\xE03C{text}",
|
||||||
DtrStyle.Style9 => $"\xE040 {text} \xE041",
|
DtrStyle.Style9 => $"\xE040 {text} \xE041",
|
||||||
_ => $"\uE044 {text}"
|
_ => $"\uE05D {text}"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ using Dalamud.Interface.Colors;
|
|||||||
using Dalamud.Interface.ImGuiFileDialog;
|
using Dalamud.Interface.ImGuiFileDialog;
|
||||||
using Dalamud.Interface.Textures.TextureWraps;
|
using Dalamud.Interface.Textures.TextureWraps;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
|
using Dalamud.Utility;
|
||||||
using MareSynchronos.API.Data;
|
using MareSynchronos.API.Data;
|
||||||
using MareSynchronos.API.Dto.User;
|
using MareSynchronos.API.Dto.User;
|
||||||
using MareSynchronos.Services;
|
using MareSynchronos.Services;
|
||||||
@@ -28,14 +29,14 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
|||||||
private IDalamudTextureWrap? _pfpTextureWrap;
|
private IDalamudTextureWrap? _pfpTextureWrap;
|
||||||
private string _profileDescription = string.Empty;
|
private string _profileDescription = string.Empty;
|
||||||
private byte[] _profileImage = [];
|
private byte[] _profileImage = [];
|
||||||
private bool _showFileDialogError = false;
|
private string _showFileDialogError = string.Empty;
|
||||||
private bool _wasOpen;
|
private bool _wasOpen;
|
||||||
|
|
||||||
public EditProfileUi(ILogger<EditProfileUi> logger, MareMediator mediator,
|
public EditProfileUi(ILogger<EditProfileUi> logger, MareMediator mediator,
|
||||||
ApiController apiController, UiSharedService uiSharedService, FileDialogManager fileDialogManager,
|
ApiController apiController, UiSharedService uiSharedService, FileDialogManager fileDialogManager,
|
||||||
ServerConfigurationManager serverConfigurationManager,
|
ServerConfigurationManager serverConfigurationManager,
|
||||||
MareProfileManager mareProfileManager, PerformanceCollectorService performanceCollectorService)
|
MareProfileManager mareProfileManager, PerformanceCollectorService performanceCollectorService)
|
||||||
: base(logger, mediator, "Snowcloak Edit Profile###SnowcloakSyncEditProfileUI", performanceCollectorService)
|
: base(logger, mediator, "Snowcloak Profile Editor###SnowcloakSyncEditProfileUI", performanceCollectorService)
|
||||||
{
|
{
|
||||||
IsOpen = false;
|
IsOpen = false;
|
||||||
this.SizeConstraints = new()
|
this.SizeConstraints = new()
|
||||||
@@ -92,20 +93,13 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
|||||||
ImGui.Image(_pfpTextureWrap.Handle, ImGuiHelpers.ScaledVector2(_pfpTextureWrap.Width, _pfpTextureWrap.Height));
|
ImGui.Image(_pfpTextureWrap.Handle, ImGuiHelpers.ScaledVector2(_pfpTextureWrap.Width, _pfpTextureWrap.Height));
|
||||||
}
|
}
|
||||||
|
|
||||||
var spacing = ImGui.GetStyle().ItemSpacing.X;
|
var spacing = ImGui.GetStyle().ItemSpacing.X + 200;
|
||||||
ImGuiHelpers.ScaledRelativeSameLine(256, spacing);
|
ImGuiHelpers.ScaledRelativeSameLine(256, spacing);
|
||||||
using (_uiSharedService.GameFont.Push())
|
using (_uiSharedService.GameFont.Push())
|
||||||
{
|
{
|
||||||
var descriptionTextSize = ImGui.CalcTextSize(profile.Description, hideTextAfterDoubleHash: false, 256f);
|
var descriptionTextSize = ImGui.CalcTextSize(profile.Description, hideTextAfterDoubleHash: false, 256f);
|
||||||
var childFrame = ImGuiHelpers.ScaledVector2(256 + ImGui.GetStyle().WindowPadding.X + ImGui.GetStyle().WindowBorderSize, 256);
|
var childFrame = ImGuiHelpers.ScaledVector2(256 + ImGui.GetStyle().WindowPadding.X + ImGui.GetStyle().WindowBorderSize, 256);
|
||||||
if (descriptionTextSize.Y > childFrame.Y)
|
_adjustedForScollBarsOnlineProfile = (descriptionTextSize.Y > childFrame.Y);
|
||||||
{
|
|
||||||
_adjustedForScollBarsOnlineProfile = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_adjustedForScollBarsOnlineProfile = false;
|
|
||||||
}
|
|
||||||
childFrame = childFrame with
|
childFrame = childFrame with
|
||||||
{
|
{
|
||||||
X = childFrame.X + (_adjustedForScollBarsOnlineProfile ? ImGui.GetStyle().ScrollbarSize : 0),
|
X = childFrame.X + (_adjustedForScollBarsOnlineProfile ? ImGui.GetStyle().ScrollbarSize : 0),
|
||||||
@@ -122,9 +116,18 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
|||||||
ImGui.Checkbox("Is NSFW", ref nsfw);
|
ImGui.Checkbox("Is NSFW", ref nsfw);
|
||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
_uiSharedService.BigText("Rules and Guidelines");
|
||||||
|
UiSharedService.ColorTextWrapped("Users that are paired with you (not paused) will be able to see your profile picture and description.", ImGuiColors.DalamudWhite);
|
||||||
|
UiSharedService.ColorTextWrapped("All users have the capability to report your profile if it violates the rules.", ImGuiColors.DalamudGrey);
|
||||||
|
UiSharedService.ColorTextWrapped(" - Please do NOT upload anything that can be considered highly illegal or obscene (beastiality, sexual acts depicting minors or anything representing a minor (including Lalafel), etc.)", ImGuiColors.DalamudRed);
|
||||||
|
UiSharedService.ColorTextWrapped(" - Please avoid the use of slurs, hate speech, threatening behaviour, etc.", ImGuiColors.DalamudRed);
|
||||||
|
UiSharedService.ColorTextWrapped(" - In the event we receive a report of an offensive profile, we may disable your profile forever or terminate your Snowcloak service account.", ImGuiColors.DalamudRed);
|
||||||
|
UiSharedService.ColorTextWrapped(" - You may not appeal any bans of your profile and or Snowcloak service account.", ImGuiColors.DalamudRed);
|
||||||
|
UiSharedService.ColorTextWrapped("Users who wish to mark their profile as NSFW should enable the toggle below.", ImGuiColors.DalamudWhite);
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
_uiSharedService.BigText("Profile Settings");
|
_uiSharedService.BigText("Profile Settings");
|
||||||
|
UiSharedService.ColorTextWrapped("Profile pictures must be cropped to 256x256px and have a file size of 250KiB or smaller.", ImGuiColors.DalamudGrey);
|
||||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.FileUpload, "Upload new profile picture"))
|
if (_uiSharedService.IconTextButton(FontAwesomeIcon.FileUpload, "Upload new profile picture"))
|
||||||
{
|
{
|
||||||
_fileDialogManager.OpenFileDialog("Select new Profile picture", ".png", (success, file) =>
|
_fileDialogManager.OpenFileDialog("Select new Profile picture", ".png", (success, file) =>
|
||||||
@@ -138,11 +141,10 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
|||||||
|
|
||||||
if (format.Width > 256 || format.Height > 256 || (fileContent.Length > 250 * 1024))
|
if (format.Width > 256 || format.Height > 256 || (fileContent.Length > 250 * 1024))
|
||||||
{
|
{
|
||||||
_showFileDialogError = true;
|
_showFileDialogError = format.Width > 256 || format.Height > 256 ? "ERROR: Image dimensions must be 256x256px or smaller." : fileContent.Length > 250 * 1024 ? "ERROR: File size was bigger than 250KiB" : "ERROR: An unknown error has occured.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_showFileDialogError = string.Empty;
|
||||||
_showFileDialogError = false;
|
|
||||||
await _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, Convert.ToBase64String(fileContent), Description: null))
|
await _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, Convert.ToBase64String(fileContent), Description: null))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
@@ -155,9 +157,9 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
|||||||
_ = _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, "", Description: null));
|
_ = _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, "", Description: null));
|
||||||
}
|
}
|
||||||
UiSharedService.AttachToolTip("Clear your currently uploaded profile picture");
|
UiSharedService.AttachToolTip("Clear your currently uploaded profile picture");
|
||||||
if (_showFileDialogError)
|
if (!_showFileDialogError.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
UiSharedService.ColorTextWrapped("The profile picture must be a PNG file with a maximum height and width of 256px and 250KiB size", ImGuiColors.DalamudRed);
|
UiSharedService.ColorTextWrapped(_showFileDialogError, ImGuiColors.DalamudRed);
|
||||||
}
|
}
|
||||||
var isNsfw = profile.IsNSFW;
|
var isNsfw = profile.IsNSFW;
|
||||||
if (ImGui.Checkbox("Profile is NSFW", ref isNsfw))
|
if (ImGui.Checkbox("Profile is NSFW", ref isNsfw))
|
||||||
|
@@ -9,6 +9,7 @@ public class TagHandler
|
|||||||
public const string CustomOnlineTag = "Mare_Online";
|
public const string CustomOnlineTag = "Mare_Online";
|
||||||
public const string CustomUnpairedTag = "Mare_Unpaired";
|
public const string CustomUnpairedTag = "Mare_Unpaired";
|
||||||
public const string CustomVisibleTag = "Mare_Visible";
|
public const string CustomVisibleTag = "Mare_Visible";
|
||||||
|
public const string CustomPausedTag = "Mare_Paused";
|
||||||
private readonly ServerConfigurationManager _serverConfigurationManager;
|
private readonly ServerConfigurationManager _serverConfigurationManager;
|
||||||
|
|
||||||
public TagHandler(ServerConfigurationManager serverConfigurationManager)
|
public TagHandler(ServerConfigurationManager serverConfigurationManager)
|
||||||
|
@@ -956,6 +956,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
_uiShared.BigText("UI");
|
_uiShared.BigText("UI");
|
||||||
var showCharacterNames = _configService.Current.ShowCharacterNames;
|
var showCharacterNames = _configService.Current.ShowCharacterNames;
|
||||||
var showVisibleSeparate = _configService.Current.ShowVisibleUsersSeparately;
|
var showVisibleSeparate = _configService.Current.ShowVisibleUsersSeparately;
|
||||||
|
var sortSyncshellByVRAM = _configService.Current.SortSyncshellsByVRAM;
|
||||||
var showOfflineSeparate = _configService.Current.ShowOfflineUsersSeparately;
|
var showOfflineSeparate = _configService.Current.ShowOfflineUsersSeparately;
|
||||||
var showProfiles = _configService.Current.ProfilesShow;
|
var showProfiles = _configService.Current.ProfilesShow;
|
||||||
var showNsfwProfiles = _configService.Current.ProfilesAllowNsfw;
|
var showNsfwProfiles = _configService.Current.ProfilesAllowNsfw;
|
||||||
@@ -1074,13 +1075,20 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
_configService.Save();
|
_configService.Save();
|
||||||
}
|
}
|
||||||
_uiShared.DrawHelpText("This will show all currently visible users in a special 'Visible' group in the main UI.");
|
_uiShared.DrawHelpText("This will show all currently visible users in a special 'Visible' group in the main UI.");
|
||||||
|
if (ImGui.Checkbox("Sort visible syncshell users by VRAM usage", ref sortSyncshellByVRAM))
|
||||||
|
{
|
||||||
|
_configService.Current.SortSyncshellsByVRAM = sortSyncshellByVRAM;
|
||||||
|
_logger.LogWarning("Changing value: {sortSyncshellsByVRAM}", sortSyncshellByVRAM);
|
||||||
|
|
||||||
if (ImGui.Checkbox("Show separate Offline group", ref showOfflineSeparate))
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("This will put users using the most VRAM in a syncshell at the top of the list.");
|
||||||
|
if (ImGui.Checkbox("Group users by connection status", ref showOfflineSeparate))
|
||||||
{
|
{
|
||||||
_configService.Current.ShowOfflineUsersSeparately = showOfflineSeparate;
|
_configService.Current.ShowOfflineUsersSeparately = showOfflineSeparate;
|
||||||
_configService.Save();
|
_configService.Save();
|
||||||
}
|
}
|
||||||
_uiShared.DrawHelpText("This will show all currently offline users in a special 'Offline' group in the main UI.");
|
_uiShared.DrawHelpText("This will categorize users by their connection status in the main UI.");
|
||||||
|
|
||||||
if (ImGui.Checkbox("Show player names", ref showCharacterNames))
|
if (ImGui.Checkbox("Show player names", ref showCharacterNames))
|
||||||
{
|
{
|
||||||
|
@@ -20,7 +20,7 @@ public class PngHdr
|
|||||||
|
|
||||||
stream.ReadExactly(buffer[..8]);
|
stream.ReadExactly(buffer[..8]);
|
||||||
|
|
||||||
uint ihdrLength = BitConverter.ToUInt32(buffer);
|
uint ihdrLength = ReadBigEndianUInt32(buffer[..4]);
|
||||||
|
|
||||||
// The next four bytes will be the length of the IHDR section (it should be 13 bytes but we only need 8)
|
// The next four bytes will be the length of the IHDR section (it should be 13 bytes but we only need 8)
|
||||||
if (ihdrLength < 8)
|
if (ihdrLength < 8)
|
||||||
@@ -32,8 +32,8 @@ public class PngHdr
|
|||||||
|
|
||||||
stream.ReadExactly(buffer[..8]);
|
stream.ReadExactly(buffer[..8]);
|
||||||
|
|
||||||
uint width = BitConverter.ToUInt32(buffer);
|
uint width = ReadBigEndianUInt32(buffer[..4]);
|
||||||
uint height = BitConverter.ToUInt32(buffer[4..]);
|
uint height = ReadBigEndianUInt32(buffer[4..8]);
|
||||||
|
|
||||||
// Validate the width/height are non-negative and... that's all we care about!
|
// Validate the width/height are non-negative and... that's all we care about!
|
||||||
if (width > int.MaxValue || height > int.MaxValue)
|
if (width > int.MaxValue || height > int.MaxValue)
|
||||||
@@ -46,4 +46,12 @@ public class PngHdr
|
|||||||
return InvalidSize;
|
return InvalidSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// Minimal helper for big-endian conversion
|
||||||
|
private static uint ReadBigEndianUInt32(ReadOnlySpan<byte> bytes)
|
||||||
|
{
|
||||||
|
return ((uint)bytes[0] << 24) |
|
||||||
|
((uint)bytes[1] << 16) |
|
||||||
|
((uint)bytes[2] << 8) |
|
||||||
|
bytes[3];
|
||||||
|
}
|
||||||
|
}
|
@@ -121,7 +121,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
|||||||
{
|
{
|
||||||
Logger.LogWarning("Multiple secret keys for current character");
|
Logger.LogWarning("Multiple secret keys for current character");
|
||||||
_connectionDto = null;
|
_connectionDto = null;
|
||||||
Mediator.Publish(new NotificationMessage("Multiple Identical Characters detected", "Your Service configuration has multiple characters with the same name and world set up. Delete the duplicates in the character management to be able to connect to Mare.",
|
Mediator.Publish(new NotificationMessage("Multiple Identical Characters detected", "Your Service configuration has multiple characters with the same name and world set up. Delete the duplicates in the character management to be able to connect.",
|
||||||
NotificationType.Error));
|
NotificationType.Error));
|
||||||
await StopConnection(ServerState.MultiChara).ConfigureAwait(false);
|
await StopConnection(ServerState.MultiChara).ConfigureAwait(false);
|
||||||
_connectionCancellationTokenSource?.Cancel();
|
_connectionCancellationTokenSource?.Cancel();
|
||||||
@@ -183,10 +183,12 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
|||||||
|
|
||||||
_connectionDto = await GetConnectionDto().ConfigureAwait(false);
|
_connectionDto = await GetConnectionDto().ConfigureAwait(false);
|
||||||
|
|
||||||
|
await CheckClientHealth().ConfigureAwait(false);
|
||||||
|
|
||||||
ServerState = ServerState.Connected;
|
ServerState = ServerState.Connected;
|
||||||
|
|
||||||
var currentClientVer = Assembly.GetExecutingAssembly().GetName().Version!;
|
var currentClientVer = Assembly.GetExecutingAssembly().GetName().Version!;
|
||||||
|
|
||||||
if (_connectionDto.ServerVersion != IMareHub.ApiVersion)
|
if (_connectionDto.ServerVersion != IMareHub.ApiVersion)
|
||||||
{
|
{
|
||||||
if (_connectionDto.CurrentClientVersion > currentClientVer)
|
if (_connectionDto.CurrentClientVersion > currentClientVer)
|
||||||
@@ -308,14 +310,18 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
|||||||
_ = Task.Run(async () => await StopConnection(ServerState.Disconnected).ConfigureAwait(false));
|
_ = Task.Run(async () => await StopConnection(ServerState.Disconnected).ConfigureAwait(false));
|
||||||
_connectionCancellationTokenSource?.Cancel();
|
_connectionCancellationTokenSource?.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ClientHealthCheck(CancellationToken ct)
|
private async Task ClientHealthCheck(CancellationToken ct)
|
||||||
{
|
{
|
||||||
while (!ct.IsCancellationRequested && _mareHub != null)
|
while (!ct.IsCancellationRequested && _mareHub != null)
|
||||||
{
|
{
|
||||||
await Task.Delay(TimeSpan.FromSeconds(30), ct).ConfigureAwait(false);
|
await Task.Delay(TimeSpan.FromSeconds(30), ct).ConfigureAwait(false);
|
||||||
Logger.LogDebug("Checking Client Health State");
|
var healthy = await CheckClientHealth().ConfigureAwait(false);
|
||||||
_ = await CheckClientHealth().ConfigureAwait(false);
|
if (!healthy || _mareHub.State != HubConnectionState.Connected)
|
||||||
|
{
|
||||||
|
Logger.LogWarning("Health check failed, forcing reconnect. ClientHealth: {0} HubConnected: {1}", healthy, _mareHub.State != HubConnectionState.Connected);
|
||||||
|
await ForceResetConnection().ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,7 +397,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
|||||||
{
|
{
|
||||||
var users = await GroupsGetUsersInGroup(group).ConfigureAwait(false);
|
var users = await GroupsGetUsersInGroup(group).ConfigureAwait(false);
|
||||||
foreach (var user in users)
|
foreach (var user in users)
|
||||||
{
|
{
|
||||||
Logger.LogDebug("Group Pair: {user}", user);
|
Logger.LogDebug("Group Pair: {user}", user);
|
||||||
_pairManager.AddGroupPair(user);
|
_pairManager.AddGroupPair(user);
|
||||||
}
|
}
|
||||||
@@ -478,5 +484,30 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
|||||||
|
|
||||||
ServerState = state;
|
ServerState = state;
|
||||||
}
|
}
|
||||||
|
//Because this plugin really likes to bug out with connections, lets "fix" it....
|
||||||
|
public async Task ForceResetConnection()
|
||||||
|
{
|
||||||
|
if (!_initialized) return;
|
||||||
|
Logger.LogInformation("ForceReconnect called");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await StopConnection(ServerState.Disconnected).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Cancel any ongoing health checks to prevent conflicts
|
||||||
|
_healthCheckTokenSource?.Cancel();
|
||||||
|
_healthCheckTokenSource?.Dispose();
|
||||||
|
_healthCheckTokenSource = null;
|
||||||
|
|
||||||
|
await CreateConnections().ConfigureAwait(false);
|
||||||
|
|
||||||
|
Logger.LogInformation("ForceReconnect completed successfully");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex, "Failure during ForceReconnect, disconnecting");
|
||||||
|
await StopConnection(ServerState.Disconnected).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#pragma warning restore MA0040
|
#pragma warning restore MA0040
|
BIN
MareSynchronos/images/logo.png
Normal file
BIN
MareSynchronos/images/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
@@ -10,9 +10,9 @@
|
|||||||
},
|
},
|
||||||
"DalamudPackager": {
|
"DalamudPackager": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[13.0.0, )",
|
"requested": "[13.1.0, )",
|
||||||
"resolved": "13.0.0",
|
"resolved": "13.1.0",
|
||||||
"contentHash": "Mb3cUDSK/vDPQ8gQIeuCw03EMYrej1B4J44a1AvIJ9C759p9XeqdU9Hg4WgOmlnlPe0G7ILTD32PKSUpkQNa8w=="
|
"contentHash": "XdoNhJGyFby5M/sdcRhnc5xTop9PHy+H50PTWpzLhJugjB19EDBiHD/AsiDF66RETM+0qKUdJBZrNuebn7qswQ=="
|
||||||
},
|
},
|
||||||
"DotNet.ReproducibleBuilds": {
|
"DotNet.ReproducibleBuilds": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
@@ -22,11 +22,11 @@
|
|||||||
},
|
},
|
||||||
"Downloader": {
|
"Downloader": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[3.3.4, )",
|
"requested": "[4.0.3, )",
|
||||||
"resolved": "3.3.4",
|
"resolved": "4.0.3",
|
||||||
"contentHash": "/M/c80e1L0WW1XrLSSiQhgFxk8rrfbpWiWDn2CeBg1tPD393Neo+v184yG/ThyhE9rrNp36yCrugiCmEbRf+VQ==",
|
"contentHash": "Vg1+UqPDstpMw2CKXV9XvB8jKHC95KQfbqPxQXvOMRMFnTov4Ixvvw6GZV5DXLnKuL2sfnmVYX9CaQtcURia1Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.Extensions.Logging.Abstractions": "8.0.1"
|
"Microsoft.Extensions.Logging.Abstractions": "8.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Glamourer.Api": {
|
"Glamourer.Api": {
|
||||||
@@ -55,11 +55,28 @@
|
|||||||
"System.IO.Pipelines": "6.0.3"
|
"System.IO.Pipelines": "6.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"MessagePack": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[3.1.4, )",
|
||||||
|
"resolved": "3.1.4",
|
||||||
|
"contentHash": "BH0wlHWmVoZpbAPyyt2Awbq30C+ZsS3eHSkYdnyUAbqVJ22fAJDzn2xTieBeoT5QlcBzp61vHcv878YJGfi3mg==",
|
||||||
|
"dependencies": {
|
||||||
|
"MessagePack.Annotations": "3.1.4",
|
||||||
|
"MessagePackAnalyzer": "3.1.4",
|
||||||
|
"Microsoft.NET.StringTools": "17.11.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MessagePack.Annotations": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[3.1.4, )",
|
||||||
|
"resolved": "3.1.4",
|
||||||
|
"contentHash": "aVWrDAkCdqxwQsz/q0ldPh2EFn48M99YUzE9OvZjMq2RNLKz4o2z88iGFvSvbMqOWRweRvKPHBJZe22PRqzslQ=="
|
||||||
|
},
|
||||||
"Meziantou.Analyzer": {
|
"Meziantou.Analyzer": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[2.0.212, )",
|
"requested": "[2.0.213, )",
|
||||||
"resolved": "2.0.212",
|
"resolved": "2.0.213",
|
||||||
"contentHash": "U91ktjjTRTccUs3Lk+hrLD9vW+2+lhnsOf4G1GpRSJi1pLn3uK5CU6wGP9Bmz1KlJs6Oz1GGoMhxQBoqQsmAuQ=="
|
"contentHash": "LHnFGBqhlBjbf8Uo4OIzGM0llRxFrIMuo/hP9oHq+aldS+28G4LqG12LK0co9b+S0yj1Vbf0rclDHN0Ji2DTkA=="
|
||||||
},
|
},
|
||||||
"Microsoft.AspNetCore.SignalR.Client": {
|
"Microsoft.AspNetCore.SignalR.Client": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
@@ -133,6 +150,12 @@
|
|||||||
"Microsoft.IdentityModel.Tokens": "8.14.0"
|
"Microsoft.IdentityModel.Tokens": "8.14.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"System.IO.Pipelines": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[9.0.8, )",
|
||||||
|
"resolved": "9.0.8",
|
||||||
|
"contentHash": "6vPmJt73mgUo1gzc/OcXlJvClz/2jxZ4TQPRfriVaLoGRH2mye530D9WHJYbFQRNMxF3PWCoeofsFdCyN7fLzA=="
|
||||||
|
},
|
||||||
"K4os.Compression.LZ4": {
|
"K4os.Compression.LZ4": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "1.3.8",
|
"resolved": "1.3.8",
|
||||||
@@ -143,19 +166,10 @@
|
|||||||
"resolved": "1.0.8",
|
"resolved": "1.0.8",
|
||||||
"contentHash": "Wp2F7BamQ2Q/7Hk834nV9vRQapgcr8kgv9Jvfm8J3D0IhDqZMMl+a2yxUq5ltJitvXvQfB8W6K4F4fCbw/P6YQ=="
|
"contentHash": "Wp2F7BamQ2Q/7Hk834nV9vRQapgcr8kgv9Jvfm8J3D0IhDqZMMl+a2yxUq5ltJitvXvQfB8W6K4F4fCbw/P6YQ=="
|
||||||
},
|
},
|
||||||
"MessagePack": {
|
"MessagePackAnalyzer": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "2.5.187",
|
"resolved": "3.1.4",
|
||||||
"contentHash": "uW4j8m4Nc+2Mk5n6arOChavJ9bLjkis0qWASOj2h2OwmfINuzYv+mjCHUymrYhmyyKTu3N+ObtTXAY4uQ7jIhg==",
|
"contentHash": "CTaSsN/liJ7MhLCAB7Z4ZLBNuVGCq9lt2BT/cbrc9vzGv89yK3CqIA+z9T19a11eQYl9etZHL6MQJgCqECRVpg=="
|
||||||
"dependencies": {
|
|
||||||
"MessagePack.Annotations": "2.5.187",
|
|
||||||
"Microsoft.NET.StringTools": "17.6.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"MessagePack.Annotations": {
|
|
||||||
"type": "Transitive",
|
|
||||||
"resolved": "2.5.198",
|
|
||||||
"contentHash": "3U9OvqQGTra+Mz1k1zfNAScSdNHobnqtQ51qdMGUZppkNDZJl0X/igq6Qz5zDBLEZoYqZrFtZwFx6wBJHHI8BA=="
|
|
||||||
},
|
},
|
||||||
"Microsoft.AspNetCore.Connections.Abstractions": {
|
"Microsoft.AspNetCore.Connections.Abstractions": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
@@ -499,19 +513,14 @@
|
|||||||
},
|
},
|
||||||
"Microsoft.NET.StringTools": {
|
"Microsoft.NET.StringTools": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "17.6.3",
|
"resolved": "17.11.4",
|
||||||
"contentHash": "N0ZIanl1QCgvUumEL1laasU0a7sOE5ZwLZVTn0pAePnfhq8P7SvTjF8Axq+CnavuQkmdQpGNXQ1efZtu5kDFbA=="
|
"contentHash": "mudqUHhNpeqIdJoUx2YDWZO/I9uEDYVowan89R6wsomfnUJQk6HteoQTlNjZDixhT2B4IXMkMtgZtoceIjLRmA=="
|
||||||
},
|
},
|
||||||
"System.Diagnostics.EventLog": {
|
"System.Diagnostics.EventLog": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "9.0.8",
|
"resolved": "9.0.8",
|
||||||
"contentHash": "gebRF3JLLJ76jz1CQpvwezNapZUjFq20JQsaGHzBH0DzlkHBLpdhwkOei9usiOkIGMwU/L0ALWpNe1JE+5/itw=="
|
"contentHash": "gebRF3JLLJ76jz1CQpvwezNapZUjFq20JQsaGHzBH0DzlkHBLpdhwkOei9usiOkIGMwU/L0ALWpNe1JE+5/itw=="
|
||||||
},
|
},
|
||||||
"System.IO.Pipelines": {
|
|
||||||
"type": "Transitive",
|
|
||||||
"resolved": "6.0.3",
|
|
||||||
"contentHash": "ryTgF+iFkpGZY1vRQhfCzX0xTdlV3pyaTTqRu2ETbEv+HlV7O6y7hyQURnghNIXvctl5DuZ//Dpks6HdL/Txgw=="
|
|
||||||
},
|
|
||||||
"System.Net.ServerSentEvents": {
|
"System.Net.ServerSentEvents": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "9.0.8",
|
"resolved": "9.0.8",
|
||||||
@@ -525,8 +534,11 @@
|
|||||||
"maresynchronos.api": {
|
"maresynchronos.api": {
|
||||||
"type": "Project",
|
"type": "Project",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"MessagePack.Annotations": "[2.5.198, )"
|
"MessagePack.Annotations": "[2.5.129, )"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"snowcloaksync": {
|
||||||
|
"type": "Project"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
SnowcloakSync/SnowcloakSync.csproj
Normal file
9
SnowcloakSync/SnowcloakSync.csproj
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
9
SnowcloakSync/Utils/Colours.cs
Normal file
9
SnowcloakSync/Utils/Colours.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace SnowcloakSync.Utils
|
||||||
|
{
|
||||||
|
public static class Colours
|
||||||
|
{
|
||||||
|
public static readonly Vector4 _snowcloakOnline = new(0.4275f, 0.6863f, 1f, 1f);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user