diff --git a/.editorconfig b/.editorconfig index 57fc97c..6724ee4 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,15 +1,135 @@ -[*] -indent_style = space -tab_width = 4 -indent_size = 4 -trim_trailing_whitespace = true -insert_final_newline = true +[*] +indent_style=space +tab_width=4 +indent_size=4 +trim_trailing_whitespace=true +insert_final_newline=false # JetBrains Rider custom properties for code formatting styles resharper_csharp_brace_style=next_line -resharper_braces_for_ifelse=not_required resharper_csharp_braces_for_foreach=not_required resharper_csharp_braces_for_for=not_required -resharper_csharp_braces_for_using=not_required -resharper_csharp_braces_for_while=not_required \ No newline at end of file +resharper_csharp_braces_for_while=not_required +charset=utf-8-bom +end_of_line=crlf + +# Microsoft .NET properties +csharp_new_line_before_members_in_object_initializers=false +csharp_preferred_modifier_order=public, private, protected, internal, file, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async, required:suggestion +csharp_style_prefer_utf8_string_literals=true:suggestion +csharp_style_var_elsewhere=true:suggestion +csharp_style_var_for_built_in_types=true:suggestion +csharp_style_var_when_type_is_apparent=true:suggestion +dotnet_naming_rule.private_constants_rule.import_to_resharper=True +dotnet_naming_rule.private_constants_rule.resharper_description=Constant fields (private) +dotnet_naming_rule.private_constants_rule.resharper_guid=236f7aa5-7b06-43ca-bf2a-9b31bfcff09a +dotnet_naming_rule.private_constants_rule.severity=warning +dotnet_naming_rule.private_constants_rule.style=upper_camel_case_style +dotnet_naming_rule.private_constants_rule.symbols=private_constants_symbols +dotnet_naming_rule.private_instance_fields_rule.import_to_resharper=True +dotnet_naming_rule.private_instance_fields_rule.resharper_description=Instance fields (private) +dotnet_naming_rule.private_instance_fields_rule.resharper_guid=4a98fdf6-7d98-4f5a-afeb-ea44ad98c70c +dotnet_naming_rule.private_instance_fields_rule.severity=warning +dotnet_naming_rule.private_instance_fields_rule.style=upper_camel_case_style +dotnet_naming_rule.private_instance_fields_rule.symbols=private_instance_fields_symbols +dotnet_naming_rule.private_static_fields_rule.import_to_resharper=True +dotnet_naming_rule.private_static_fields_rule.resharper_description=Static fields (private) +dotnet_naming_rule.private_static_fields_rule.resharper_guid=f9fce829-e6f4-4cb2-80f1-5497c44f51df +dotnet_naming_rule.private_static_fields_rule.severity=warning +dotnet_naming_rule.private_static_fields_rule.style=lower_camel_case_style +dotnet_naming_rule.private_static_fields_rule.symbols=private_static_fields_symbols +dotnet_naming_rule.private_static_readonly_rule.import_to_resharper=True +dotnet_naming_rule.private_static_readonly_rule.resharper_description=Static readonly fields (private) +dotnet_naming_rule.private_static_readonly_rule.resharper_guid=15b5b1f1-457c-4ca6-b278-5615aedc07d3 +dotnet_naming_rule.private_static_readonly_rule.severity=warning +dotnet_naming_rule.private_static_readonly_rule.style=upper_camel_case_style +dotnet_naming_rule.private_static_readonly_rule.symbols=private_static_readonly_symbols +dotnet_naming_rule.unity_serialized_field_rule.import_to_resharper=True +dotnet_naming_rule.unity_serialized_field_rule.resharper_description=Unity serialized field +dotnet_naming_rule.unity_serialized_field_rule.resharper_guid=5f0fdb63-c892-4d2c-9324-15c80b22a7ef +dotnet_naming_rule.unity_serialized_field_rule.severity=warning +dotnet_naming_rule.unity_serialized_field_rule.style=lower_camel_case_style_1 +dotnet_naming_rule.unity_serialized_field_rule.symbols=unity_serialized_field_symbols +dotnet_naming_style.lower_camel_case_style.capitalization=camel_case +dotnet_naming_style.lower_camel_case_style.required_prefix=_ +dotnet_naming_style.lower_camel_case_style_1.capitalization=camel_case +dotnet_naming_style.upper_camel_case_style.capitalization=pascal_case +dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities=private +dotnet_naming_symbols.private_constants_symbols.applicable_kinds=field +dotnet_naming_symbols.private_constants_symbols.required_modifiers=const +dotnet_naming_symbols.private_constants_symbols.resharper_applicable_kinds=constant_field +dotnet_naming_symbols.private_constants_symbols.resharper_required_modifiers=any +dotnet_naming_symbols.private_instance_fields_symbols.applicable_accessibilities=private +dotnet_naming_symbols.private_instance_fields_symbols.applicable_kinds=field +dotnet_naming_symbols.private_instance_fields_symbols.resharper_applicable_kinds=field,readonly_field +dotnet_naming_symbols.private_instance_fields_symbols.resharper_required_modifiers=instance +dotnet_naming_symbols.private_static_fields_symbols.applicable_accessibilities=private +dotnet_naming_symbols.private_static_fields_symbols.applicable_kinds=field +dotnet_naming_symbols.private_static_fields_symbols.required_modifiers=static +dotnet_naming_symbols.private_static_fields_symbols.resharper_applicable_kinds=field +dotnet_naming_symbols.private_static_fields_symbols.resharper_required_modifiers=static +dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities=private +dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds=field +dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers=readonly,static +dotnet_naming_symbols.private_static_readonly_symbols.resharper_applicable_kinds=readonly_field +dotnet_naming_symbols.private_static_readonly_symbols.resharper_required_modifiers=static +dotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities=* +dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds= +dotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds=unity_serialised_field +dotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers=instance +dotnet_style_parentheses_in_arithmetic_binary_operators=never_if_unnecessary:none +dotnet_style_parentheses_in_other_binary_operators=always_for_clarity:none +dotnet_style_parentheses_in_relational_binary_operators=never_if_unnecessary:none +dotnet_style_predefined_type_for_locals_parameters_members=true:suggestion +dotnet_style_predefined_type_for_member_access=true:suggestion +dotnet_style_qualification_for_event=false:suggestion +dotnet_style_qualification_for_field=false:suggestion +dotnet_style_qualification_for_method=false:suggestion +dotnet_style_qualification_for_property=false:suggestion +dotnet_style_require_accessibility_modifiers=for_non_interface_members:suggestion + +# ReSharper properties +resharper_autodetect_indent_settings=true +resharper_csharp_insert_final_newline=false +resharper_formatter_off_tag=@formatter:off +resharper_formatter_on_tag=@formatter:on +resharper_formatter_tags_enabled=true +resharper_fsharp_insert_final_newline=false +resharper_html_insert_final_newline=false +resharper_resx_insert_final_newline=false +resharper_shaderlab_insert_final_newline=false +resharper_T4_insert_final_newline=false +resharper_use_indent_from_vs=false +resharper_vb_insert_final_newline=false +resharper_xmldoc_insert_final_newline=false +resharper_xml_insert_final_newline=false + +# ReSharper inspection severities +resharper_arrange_redundant_parentheses_highlighting=hint +resharper_arrange_this_qualifier_highlighting=hint +resharper_arrange_type_member_modifiers_highlighting=hint +resharper_arrange_type_modifiers_highlighting=hint +resharper_built_in_type_reference_style_for_member_access_highlighting=hint +resharper_built_in_type_reference_style_highlighting=hint +resharper_razor_assembly_not_resolved_highlighting=warning +resharper_redundant_base_qualifier_highlighting=warning +resharper_suggest_var_or_type_built_in_types_highlighting=hint +resharper_suggest_var_or_type_elsewhere_highlighting=hint +resharper_suggest_var_or_type_simple_types_highlighting=hint +resharper_web_config_module_not_resolved_highlighting=warning +resharper_web_config_type_not_resolved_highlighting=warning +resharper_web_config_wrong_module_highlighting=warning + +[{*.har,*.jsb2,*.jsb3,*.json,*.jsonc,*.postman_collection,*.postman_collection.json,*.postman_environment,*.postman_environment.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}] +indent_style=space +indent_size=2 + +[{*.yaml,*.yml}] +indent_style=space +indent_size=2 + +[*.{appxmanifest,asax,ascx,aspx,axaml,build,c,c++,c++m,cc,ccm,cginc,compute,cp,cpp,cppm,cs,cshtml,cu,cuh,cxx,cxxm,dtd,fs,fsi,fsscript,fsx,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,ixx,master,ml,mli,mpp,mq4,mq5,mqh,mxx,nuspec,paml,razor,resw,resx,shader,skin,tpp,usf,ush,uxml,vb,xaml,xamlx,xoml,xsd}] +indent_style=space +indent_size=4 +tab_width=4 diff --git a/ChatTwo/Configuration.cs b/ChatTwo/Configuration.cs index b799ab7..f35ef6d 100755 --- a/ChatTwo/Configuration.cs +++ b/ChatTwo/Configuration.cs @@ -56,8 +56,12 @@ internal class Configuration : IPluginConfiguration public bool OverrideStyle; public string? ChosenStyle; - internal void UpdateFrom(Configuration other) + internal void UpdateFrom(Configuration other, bool backToOriginal) { + if (backToOriginal) + foreach (var tab in Tabs.Where(t => t.PopOut)) + tab.PopOut = false; + HideChat = other.HideChat; HideDuringCutscenes = other.HideDuringCutscenes; HideWhenNotLoggedIn = other.HideWhenNotLoggedIn; @@ -175,7 +179,7 @@ internal class Tab public string Name = Language.Tab_DefaultName; public Dictionary ChatCodes = new(); public bool ExtraChatAll; - public HashSet ExtraChatChannels = new(); + public HashSet ExtraChatChannels = []; [Obsolete("Use UnreadMode instead")] public bool DisplayUnread = true; @@ -194,9 +198,9 @@ internal class Tab public SemaphoreSlim MessagesMutex = new(1, 1); [NonSerialized] - public List Messages = new(); + public List Messages = []; [NonSerialized] - public HashSet TrackedMessageIds = new(); + public HashSet TrackedMessageIds = []; [NonSerialized] public InputChannel? PreviousChannel; @@ -204,13 +208,18 @@ internal class Tab [NonSerialized] public Guid Identifier = Guid.NewGuid(); - ~Tab() { MessagesMutex.Dispose(); } + ~Tab() + { + MessagesMutex.Dispose(); + } - internal bool Contains(Message message) { + internal bool Contains(Message message) + { return TrackedMessageIds.Contains(message.Id); } - internal bool Matches(Message message) { + internal bool Matches(Message message) + { if (message.ExtraChatChannel != Guid.Empty) return ExtraChatAll || ExtraChatChannels.Contains(message.ExtraChatChannel); @@ -221,11 +230,14 @@ internal class Tab } internal void AddMessage(Message message, bool unread = true) { - if (Contains(message)) return; + if (Contains(message)) + return; + MessagesMutex.Wait(); TrackedMessageIds.Add(message.Id); Messages.Add(message); - while (Messages.Count > MessageManager.MessageDisplayLimit) { + while (Messages.Count > MessageManager.MessageDisplayLimit) + { TrackedMessageIds.Remove(Messages[0].Id); Messages.RemoveAt(0); } @@ -235,7 +247,8 @@ internal class Tab Unread += 1; } - internal void Clear() { + internal void Clear() + { MessagesMutex.Wait(); Messages.Clear(); TrackedMessageIds.Clear(); @@ -259,6 +272,7 @@ internal class Tab PopOut = PopOut, IndependentOpacity = IndependentOpacity, Opacity = Opacity, + Identifier = Identifier, }; } } diff --git a/ChatTwo/PayloadHandler.cs b/ChatTwo/PayloadHandler.cs index 035fc71..5f481e9 100755 --- a/ChatTwo/PayloadHandler.cs +++ b/ChatTwo/PayloadHandler.cs @@ -12,6 +12,7 @@ using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Interface.Internal; using Dalamud.Interface.Internal.Notifications; using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Component.GUI; @@ -73,14 +74,14 @@ public sealed class PayloadHandler { var (chunk, payload) = Popup.Value; - if (!ImGui.BeginPopup(PopupId)) + using var popup = ImRaii.Popup(PopupId); + if (!popup.Success) { Popup = null; return; } - ImGui.PushID(PopupId); - + using var id = ImRaii.PushId(PopupId); var drawn = false; switch (payload) { @@ -100,9 +101,6 @@ public sealed class PayloadHandler { ContextFooter(drawn, chunk); Integrations(chunk, payload); - - ImGui.PopID(); - ImGui.EndPopup(); } private void Integrations(Chunk chunk, Payload? payload) diff --git a/ChatTwo/Ui/ChatLogWindow.cs b/ChatTwo/Ui/ChatLogWindow.cs index a1a77cd..b276d47 100644 --- a/ChatTwo/Ui/ChatLogWindow.cs +++ b/ChatTwo/Ui/ChatLogWindow.cs @@ -1157,7 +1157,7 @@ public sealed class ChatLogWindow : Window } internal readonly List PopOutDocked = []; - internal readonly Dictionary PopOutWindows = new(); + internal readonly HashSet PopOutWindows = []; private void AddPopOutsToDraw() { HandlerLender.ResetCounter(); @@ -1174,13 +1174,13 @@ public sealed class ChatLogWindow : Window if (!tab.PopOut) continue; - if (PopOutWindows.ContainsKey($"{tab.Name}{i}")) + if (PopOutWindows.Contains(tab.Identifier)) continue; var window = new Popout(this, tab, i); Plugin.WindowSystem.AddWindow(window); - PopOutWindows.Add($"{tab.Name}{i}", window); + PopOutWindows.Add(tab.Identifier); } } diff --git a/ChatTwo/Ui/Popout.cs b/ChatTwo/Ui/Popout.cs index 3883a67..3684d83 100644 --- a/ChatTwo/Ui/Popout.cs +++ b/ChatTwo/Ui/Popout.cs @@ -26,6 +26,12 @@ internal class Popout : Window DisableWindowSounds = true; } + public override void PreOpenCheck() + { + if (!Tab.PopOut) + IsOpen = false; + } + public override bool DrawConditions() { return !ChatLogWindow.IsHidden; @@ -48,9 +54,10 @@ internal class Popout : Window public override void Draw() { - using var id = ImRaii.PushId($"popout-{Tab.Name}"); + using var id = ImRaii.PushId($"popout-{Tab.Identifier}"); - if (!ChatLogWindow.Plugin.Config.ShowPopOutTitleBar) { + if (!ChatLogWindow.Plugin.Config.ShowPopOutTitleBar) + { ImGui.TextUnformatted(Tab.Name); ImGui.Separator(); } @@ -69,7 +76,7 @@ internal class Popout : Window public override void OnClose() { - ChatLogWindow.PopOutWindows.Remove($"{Tab.Name}{Idx}"); + ChatLogWindow.PopOutWindows.Remove(Tab.Identifier); ChatLogWindow.Plugin.WindowSystem.RemoveWindow(this); Tab.PopOut = false; diff --git a/ChatTwo/Ui/Settings.cs b/ChatTwo/Ui/Settings.cs index f84a4bb..a5d73f6 100755 --- a/ChatTwo/Ui/Settings.cs +++ b/ChatTwo/Ui/Settings.cs @@ -65,7 +65,7 @@ public sealed class SettingsWindow : Window private void Initialise() { - Mutable.UpdateFrom(Plugin.Config); + Mutable.UpdateFrom(Plugin.Config, false); } public override void Draw() @@ -153,7 +153,7 @@ public sealed class SettingsWindow : Window || Math.Abs(Mutable.JapaneseFontSize - Plugin.Config.JapaneseFontSize) > 0.001 || Math.Abs(Mutable.SymbolsFontSize - Plugin.Config.SymbolsFontSize) > 0.001; - Plugin.Config.UpdateFrom(Mutable); + Plugin.Config.UpdateFrom(Mutable, true); // save after 60 frames have passed, which should hopefully not // commit any changes that cause a crash