mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-26 11:10:34 +08:00
fix(Window): 修复全屏标题栏 Logo 重复挂载崩溃
This commit is contained in:
@@ -35,8 +35,8 @@
|
||||
VerticalAlignment="Center"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="{Binding $parent[atom:Window].EffectiveLogo}"
|
||||
ContentTemplate="{Binding $parent[atom:Window].EffectiveLogoTemplate}"
|
||||
Content="{Binding $parent[atom:Window].EffectiveFullscreenLogo}"
|
||||
ContentTemplate="{Binding $parent[atom:Window].EffectiveFullscreenLogoTemplate}"
|
||||
IsVisible="{Binding $parent[atom:Window].IsEffectiveFullscreenLogoVisible}"/>
|
||||
<TextBlock Name="FullscreenTitleText"
|
||||
HorizontalAlignment="Left"
|
||||
|
||||
@@ -102,8 +102,8 @@
|
||||
VerticalAlignment="Center"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="{Binding $parent[atom:Window].EffectiveLogo}"
|
||||
ContentTemplate="{Binding $parent[atom:Window].EffectiveLogoTemplate}"
|
||||
Content="{Binding $parent[atom:Window].EffectiveFullscreenLogo}"
|
||||
ContentTemplate="{Binding $parent[atom:Window].EffectiveFullscreenLogoTemplate}"
|
||||
IsVisible="{Binding $parent[atom:Window].IsEffectiveFullscreenLogoVisible}"/>
|
||||
<TextBlock Name="FullscreenTitleText"
|
||||
HorizontalAlignment="Left"
|
||||
@@ -180,7 +180,7 @@
|
||||
<Setter Property="CornerRadius" Value="0" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:fullscreen /template/ Panel#PART_TitleBarPresenter">
|
||||
<Style Selector="^:fullscreen /template/ ContentPresenter#PART_TitleBarPresenter">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^:fullscreen /template/ ContentPresenter#PART_TitleBar">
|
||||
|
||||
@@ -358,6 +358,16 @@ public partial class Window : AvaloniaWindow,
|
||||
nameof(EffectiveLogoTemplate),
|
||||
o => o.EffectiveLogoTemplate);
|
||||
|
||||
internal static readonly DirectProperty<Window, object?> EffectiveFullscreenLogoProperty =
|
||||
AvaloniaProperty.RegisterDirect<Window, object?>(
|
||||
nameof(EffectiveFullscreenLogo),
|
||||
o => o.EffectiveFullscreenLogo);
|
||||
|
||||
internal static readonly DirectProperty<Window, IDataTemplate?> EffectiveFullscreenLogoTemplateProperty =
|
||||
AvaloniaProperty.RegisterDirect<Window, IDataTemplate?>(
|
||||
nameof(EffectiveFullscreenLogoTemplate),
|
||||
o => o.EffectiveFullscreenLogoTemplate);
|
||||
|
||||
internal static readonly DirectProperty<Window, bool> IsEffectiveFullscreenTitleVisibleProperty =
|
||||
AvaloniaProperty.RegisterDirect<Window, bool>(
|
||||
nameof(IsEffectiveFullscreenTitleVisible),
|
||||
@@ -480,6 +490,28 @@ public partial class Window : AvaloniaWindow,
|
||||
private set => SetAndRaise(EffectiveLogoTemplateProperty, ref _effectiveLogoTemplate, value);
|
||||
}
|
||||
|
||||
private object? _effectiveFullscreenLogo;
|
||||
|
||||
internal object? EffectiveFullscreenLogo
|
||||
{
|
||||
get => _effectiveFullscreenLogo;
|
||||
private set => SetAndRaise(
|
||||
EffectiveFullscreenLogoProperty,
|
||||
ref _effectiveFullscreenLogo,
|
||||
value);
|
||||
}
|
||||
|
||||
private IDataTemplate? _effectiveFullscreenLogoTemplate;
|
||||
|
||||
internal IDataTemplate? EffectiveFullscreenLogoTemplate
|
||||
{
|
||||
get => _effectiveFullscreenLogoTemplate;
|
||||
private set => SetAndRaise(
|
||||
EffectiveFullscreenLogoTemplateProperty,
|
||||
ref _effectiveFullscreenLogoTemplate,
|
||||
value);
|
||||
}
|
||||
|
||||
private bool _isEffectiveFullscreenTitleVisible;
|
||||
|
||||
internal bool IsEffectiveFullscreenTitleVisible
|
||||
@@ -1698,7 +1730,8 @@ public partial class Window : AvaloniaWindow,
|
||||
change.Property == EffectiveLogoTemplateProperty ||
|
||||
change.Property == LogoVisibilityProperty ||
|
||||
change.Property == TitleProperty ||
|
||||
change.Property == IsTitleVisibleProperty)
|
||||
change.Property == IsTitleVisibleProperty ||
|
||||
change.Property == WindowStateProperty)
|
||||
{
|
||||
UpdateEffectiveFullscreenLogoVisible();
|
||||
}
|
||||
@@ -1712,12 +1745,28 @@ public partial class Window : AvaloniaWindow,
|
||||
private void UpdateEffectiveFullscreenLogoVisible()
|
||||
{
|
||||
var hasLogo = EffectiveLogo is not null || EffectiveLogoTemplate is not null;
|
||||
IsEffectiveFullscreenLogoVisible = LogoVisibility switch
|
||||
var isLogoVisibleByMode = LogoVisibility switch
|
||||
{
|
||||
WindowTitleBarLogoVisibility.Always => hasLogo,
|
||||
WindowTitleBarLogoVisibility.Never => false,
|
||||
_ => hasLogo && HasTitleContent(Title) && IsEffectiveFullscreenTitleVisible
|
||||
};
|
||||
IsEffectiveFullscreenLogoVisible = WindowState == WindowState.FullScreen && isLogoVisibleByMode;
|
||||
UpdateEffectiveFullscreenLogo();
|
||||
}
|
||||
|
||||
private void UpdateEffectiveFullscreenLogo()
|
||||
{
|
||||
if (IsEffectiveFullscreenLogoVisible)
|
||||
{
|
||||
EffectiveFullscreenLogo = EffectiveLogo;
|
||||
EffectiveFullscreenLogoTemplate = EffectiveLogoTemplate;
|
||||
}
|
||||
else
|
||||
{
|
||||
EffectiveFullscreenLogo = null;
|
||||
EffectiveFullscreenLogoTemplate = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasTitleContent(object? title)
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
IsHitTestVisible="False"
|
||||
Content="{TemplateBinding EffectiveLogo}"
|
||||
ContentTemplate="{TemplateBinding EffectiveLogoTemplate}"
|
||||
Content="{TemplateBinding EffectiveLogoPresenterContent}"
|
||||
ContentTemplate="{TemplateBinding EffectiveLogoPresenterContentTemplate}"
|
||||
IsVisible="{TemplateBinding IsEffectiveLogoVisible}" />
|
||||
<ContentPresenter Name="PART_LeftAddOn"
|
||||
DockPanel.Dock="Left"
|
||||
@@ -120,8 +120,8 @@
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
IsHitTestVisible="False"
|
||||
Content="{TemplateBinding EffectiveLogo}"
|
||||
ContentTemplate="{TemplateBinding EffectiveLogoTemplate}"
|
||||
Content="{TemplateBinding EffectiveLogoPresenterContent}"
|
||||
ContentTemplate="{TemplateBinding EffectiveLogoPresenterContentTemplate}"
|
||||
IsVisible="{TemplateBinding IsEffectiveLogoVisible}" />
|
||||
<ContentPresenter Name="PART_LeftAddOn"
|
||||
DockPanel.Dock="Left"
|
||||
@@ -219,8 +219,8 @@
|
||||
VerticalAlignment="Center"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="{TemplateBinding EffectiveLogo}"
|
||||
ContentTemplate="{TemplateBinding EffectiveLogoTemplate}"
|
||||
Content="{TemplateBinding EffectiveLogoPresenterContent}"
|
||||
ContentTemplate="{TemplateBinding EffectiveLogoPresenterContentTemplate}"
|
||||
IsVisible="{TemplateBinding IsEffectiveLogoVisible}" />
|
||||
<ContentPresenter Name="PART_ContentPresenter"
|
||||
HorizontalAlignment="Left"
|
||||
|
||||
@@ -169,6 +169,16 @@ public class WindowTitleBar : TemplatedControl,
|
||||
nameof(EffectiveLogoTemplate),
|
||||
o => o.EffectiveLogoTemplate);
|
||||
|
||||
internal static readonly DirectProperty<WindowTitleBar, object?> EffectiveLogoPresenterContentProperty =
|
||||
AvaloniaProperty.RegisterDirect<WindowTitleBar, object?>(
|
||||
nameof(EffectiveLogoPresenterContent),
|
||||
o => o.EffectiveLogoPresenterContent);
|
||||
|
||||
internal static readonly DirectProperty<WindowTitleBar, IDataTemplate?> EffectiveLogoPresenterContentTemplateProperty =
|
||||
AvaloniaProperty.RegisterDirect<WindowTitleBar, IDataTemplate?>(
|
||||
nameof(EffectiveLogoPresenterContentTemplate),
|
||||
o => o.EffectiveLogoPresenterContentTemplate);
|
||||
|
||||
internal static readonly DirectProperty<WindowTitleBar, bool> IsEffectiveLogoVisibleProperty =
|
||||
AvaloniaProperty.RegisterDirect<WindowTitleBar, bool>(
|
||||
nameof(IsEffectiveLogoVisible),
|
||||
@@ -234,6 +244,28 @@ public class WindowTitleBar : TemplatedControl,
|
||||
private set => SetAndRaise(EffectiveLogoTemplateProperty, ref _effectiveLogoTemplate, value);
|
||||
}
|
||||
|
||||
private object? _effectiveLogoPresenterContent;
|
||||
|
||||
internal object? EffectiveLogoPresenterContent
|
||||
{
|
||||
get => _effectiveLogoPresenterContent;
|
||||
private set => SetAndRaise(
|
||||
EffectiveLogoPresenterContentProperty,
|
||||
ref _effectiveLogoPresenterContent,
|
||||
value);
|
||||
}
|
||||
|
||||
private IDataTemplate? _effectiveLogoPresenterContentTemplate;
|
||||
|
||||
internal IDataTemplate? EffectiveLogoPresenterContentTemplate
|
||||
{
|
||||
get => _effectiveLogoPresenterContentTemplate;
|
||||
private set => SetAndRaise(
|
||||
EffectiveLogoPresenterContentTemplateProperty,
|
||||
ref _effectiveLogoPresenterContentTemplate,
|
||||
value);
|
||||
}
|
||||
|
||||
private bool _isEffectiveLogoVisible;
|
||||
|
||||
internal bool IsEffectiveLogoVisible
|
||||
@@ -486,12 +518,28 @@ public class WindowTitleBar : TemplatedControl,
|
||||
private void UpdateEffectiveLogoVisible()
|
||||
{
|
||||
var hasLogo = EffectiveLogo is not null || EffectiveLogoTemplate is not null;
|
||||
IsEffectiveLogoVisible = LogoVisibility switch
|
||||
var isLogoVisibleByMode = LogoVisibility switch
|
||||
{
|
||||
WindowTitleBarLogoVisibility.Always => hasLogo,
|
||||
WindowTitleBarLogoVisibility.Never => false,
|
||||
_ => hasLogo && ShouldShowLogoInAutoMode()
|
||||
};
|
||||
IsEffectiveLogoVisible = HostWindowState != WindowState.FullScreen && isLogoVisibleByMode;
|
||||
UpdateEffectiveLogoPresenterContent();
|
||||
}
|
||||
|
||||
private void UpdateEffectiveLogoPresenterContent()
|
||||
{
|
||||
if (IsEffectiveLogoVisible)
|
||||
{
|
||||
EffectiveLogoPresenterContent = EffectiveLogo;
|
||||
EffectiveLogoPresenterContentTemplate = EffectiveLogoTemplate;
|
||||
}
|
||||
else
|
||||
{
|
||||
EffectiveLogoPresenterContent = null;
|
||||
EffectiveLogoPresenterContentTemplate = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEffectiveTitleVisible()
|
||||
|
||||
@@ -657,10 +657,19 @@ public class WindowResizeArtifactTests
|
||||
{
|
||||
var document = XDocument.Load(GetRepoFile(
|
||||
"src/AtomUI.Desktop.Controls/Window/Themes/WindowDrawnDecorationsTheme.axaml"));
|
||||
XNamespace av = "https://github.com/avaloniaui";
|
||||
|
||||
AssertTitleBarVisibilityContract(document, "PART_TitleBar");
|
||||
AssertTitleBarVisibilityContract(document, "PART_TitleBarPresenter");
|
||||
AssertTitleBarVisibilityContract(document, "WindowTitleBarShadowBackground");
|
||||
document.Descendants(av + "Style")
|
||||
.ShouldContain(style =>
|
||||
(string?)style.Attribute("Selector") ==
|
||||
"^:fullscreen /template/ ContentPresenter#PART_TitleBarPresenter");
|
||||
document.Descendants(av + "Style")
|
||||
.ShouldNotContain(style =>
|
||||
(string?)style.Attribute("Selector") ==
|
||||
"^:fullscreen /template/ Panel#PART_TitleBarPresenter");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -1015,6 +1024,10 @@ public class WindowResizeArtifactTests
|
||||
var logoPresenter = title.Descendants().Single(element =>
|
||||
(string?)element.Attribute("Name") == "FullscreenLogoPresenter");
|
||||
logoPresenter.Attribute("DockPanel.Dock")?.Value.ShouldBe("Left");
|
||||
logoPresenter.Attribute("Content")?.Value.ShouldBe(
|
||||
"{Binding $parent[atom:Window].EffectiveFullscreenLogo}");
|
||||
logoPresenter.Attribute("ContentTemplate")?.Value.ShouldBe(
|
||||
"{Binding $parent[atom:Window].EffectiveFullscreenLogoTemplate}");
|
||||
var titleText = title.Descendants().Single(element =>
|
||||
(string?)element.Attribute("Name") == "FullscreenTitleText");
|
||||
titleText.Attribute("TextWrapping")?.Value.ShouldBe("NoWrap");
|
||||
|
||||
@@ -274,7 +274,7 @@ public class WindowTitleBarEffectiveLogoTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Runtime_Icon_Changes_Update_Fullscreen_Logo_Visibility()
|
||||
public void Fullscreen_Logo_Visibility_Is_Inactive_Until_Window_Enters_Fullscreen()
|
||||
{
|
||||
var window = new AtomUI.Desktop.Controls.Window
|
||||
{
|
||||
@@ -283,12 +283,55 @@ public class WindowTitleBarEffectiveLogoTests
|
||||
};
|
||||
|
||||
GetIsEffectiveFullscreenLogoVisible(window).ShouldBeFalse();
|
||||
GetEffectiveFullscreenLogo(window).ShouldBeNull();
|
||||
GetEffectiveFullscreenLogoTemplate(window).ShouldBeNull();
|
||||
|
||||
window.Icon = CreateIcon();
|
||||
GetIsEffectiveFullscreenLogoVisible(window).ShouldBeFalse();
|
||||
GetEffectiveFullscreenLogo(window).ShouldBeNull();
|
||||
GetEffectiveFullscreenLogoTemplate(window).ShouldBeNull();
|
||||
|
||||
window.WindowState = WindowState.FullScreen;
|
||||
GetIsEffectiveFullscreenLogoVisible(window).ShouldBeTrue();
|
||||
GetEffectiveFullscreenLogo(window).ShouldBe(window.Icon);
|
||||
GetEffectiveFullscreenLogoTemplate(window).ShouldNotBeNull();
|
||||
|
||||
window.WindowState = WindowState.Normal;
|
||||
GetIsEffectiveFullscreenLogoVisible(window).ShouldBeFalse();
|
||||
GetEffectiveFullscreenLogo(window).ShouldBeNull();
|
||||
GetEffectiveFullscreenLogoTemplate(window).ShouldBeNull();
|
||||
|
||||
window.Icon = null;
|
||||
GetIsEffectiveFullscreenLogoVisible(window).ShouldBeFalse();
|
||||
GetEffectiveFullscreenLogo(window).ShouldBeNull();
|
||||
GetEffectiveFullscreenLogoTemplate(window).ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Hosted_Title_Bar_Releases_Logo_Visibility_When_Host_Enters_Fullscreen()
|
||||
{
|
||||
var logo = new Border();
|
||||
var titleBar = new WindowTitleBar
|
||||
{
|
||||
Title = "AtomUI",
|
||||
Logo = logo,
|
||||
LogoVisibility = WindowTitleBarLogoVisibility.Always
|
||||
};
|
||||
titleBar.SetValue(WindowTitleBar.OsTypeProperty, OsType.Windows);
|
||||
|
||||
GetIsEffectiveLogoVisible(titleBar).ShouldBeTrue();
|
||||
GetEffectiveLogoPresenterContent(titleBar).ShouldBe(logo);
|
||||
GetEffectiveLogoPresenterContentTemplate(titleBar).ShouldBeNull();
|
||||
|
||||
titleBar.HostWindowState = WindowState.FullScreen;
|
||||
GetIsEffectiveLogoVisible(titleBar).ShouldBeFalse();
|
||||
GetEffectiveLogoPresenterContent(titleBar).ShouldBeNull();
|
||||
GetEffectiveLogoPresenterContentTemplate(titleBar).ShouldBeNull();
|
||||
|
||||
titleBar.HostWindowState = WindowState.Normal;
|
||||
GetIsEffectiveLogoVisible(titleBar).ShouldBeTrue();
|
||||
GetEffectiveLogoPresenterContent(titleBar).ShouldBe(logo);
|
||||
GetEffectiveLogoPresenterContentTemplate(titleBar).ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -432,6 +475,20 @@ public class WindowTitleBarEffectiveLogoTests
|
||||
.GetValue(window);
|
||||
}
|
||||
|
||||
private static object? GetEffectiveFullscreenLogo(AtomUI.Desktop.Controls.Window window)
|
||||
{
|
||||
return typeof(AtomUI.Desktop.Controls.Window)
|
||||
.GetProperty("EffectiveFullscreenLogo", BindingFlags.Instance | BindingFlags.NonPublic)!
|
||||
.GetValue(window);
|
||||
}
|
||||
|
||||
private static object? GetEffectiveFullscreenLogoTemplate(AtomUI.Desktop.Controls.Window window)
|
||||
{
|
||||
return typeof(AtomUI.Desktop.Controls.Window)
|
||||
.GetProperty("EffectiveFullscreenLogoTemplate", BindingFlags.Instance | BindingFlags.NonPublic)!
|
||||
.GetValue(window);
|
||||
}
|
||||
|
||||
private static WindowTitleBar? GetTitleBar(AtomUI.Desktop.Controls.Window window)
|
||||
{
|
||||
return typeof(AtomUI.Desktop.Controls.Window)
|
||||
@@ -446,6 +503,20 @@ public class WindowTitleBarEffectiveLogoTests
|
||||
.GetValue(titleBar)!;
|
||||
}
|
||||
|
||||
private static object? GetEffectiveLogoPresenterContent(WindowTitleBar titleBar)
|
||||
{
|
||||
return typeof(WindowTitleBar)
|
||||
.GetProperty("EffectiveLogoPresenterContent", BindingFlags.Instance | BindingFlags.NonPublic)!
|
||||
.GetValue(titleBar);
|
||||
}
|
||||
|
||||
private static object? GetEffectiveLogoPresenterContentTemplate(WindowTitleBar titleBar)
|
||||
{
|
||||
return typeof(WindowTitleBar)
|
||||
.GetProperty("EffectiveLogoPresenterContentTemplate", BindingFlags.Instance | BindingFlags.NonPublic)!
|
||||
.GetValue(titleBar);
|
||||
}
|
||||
|
||||
private static bool GetIsEffectiveFullscreenLogoVisible(AtomUI.Desktop.Controls.Window window)
|
||||
{
|
||||
return (bool)typeof(AtomUI.Desktop.Controls.Window)
|
||||
|
||||
@@ -128,6 +128,7 @@ public class WindowTitleBarLogoVisibilityTests
|
||||
source.ShouldContain("WindowTitleBarLogoVisibility.Always => hasLogo");
|
||||
source.ShouldContain("WindowTitleBarLogoVisibility.Never => false");
|
||||
source.ShouldContain("_ => hasLogo && ShouldShowLogoInAutoMode()");
|
||||
source.ShouldContain("HostWindowState != WindowState.FullScreen && isLogoVisibleByMode");
|
||||
source.ShouldContain("HostWindowState != WindowState.FullScreen");
|
||||
source.ShouldContain("OsType == OsType.macOS");
|
||||
source.ShouldContain("string text => !string.IsNullOrWhiteSpace(text)");
|
||||
@@ -198,8 +199,10 @@ public class WindowTitleBarLogoVisibilityTests
|
||||
source.ShouldContain(
|
||||
"titleBar.Bind(WindowTitleBar.LogoVisibilityProperty, this.GetObservable(LogoVisibilityProperty))");
|
||||
source.ShouldContain("IsEffectiveFullscreenLogoVisibleProperty");
|
||||
source.ShouldContain("EffectiveFullscreenLogoProperty");
|
||||
source.ShouldContain("EffectiveFullscreenLogoTemplateProperty");
|
||||
source.ShouldContain("UpdateEffectiveFullscreenLogoVisible()");
|
||||
source.ShouldContain("_ => hasLogo && HasTitleContent(Title) && IsEffectiveFullscreenTitleVisible");
|
||||
source.ShouldContain("WindowState == WindowState.FullScreen && isLogoVisibleByMode");
|
||||
// Effective Logo 模式:回退解析只进 EffectiveLogo/EffectiveLogoTemplate 渲染层,
|
||||
// 框架不再向 Logo/LogoTemplate/Icon 写入任何默认值
|
||||
source.ShouldContain("UpdateEffectiveLogo()");
|
||||
@@ -219,6 +222,12 @@ public class WindowTitleBarLogoVisibilityTests
|
||||
Regex.Matches(source, "IsVisible=\"\\{TemplateBinding IsEffectiveLogoVisible\\}\"")
|
||||
.Count
|
||||
.ShouldBe(3);
|
||||
Regex.Matches(source, "Content=\"\\{TemplateBinding EffectiveLogoPresenterContent\\}\"")
|
||||
.Count
|
||||
.ShouldBe(3);
|
||||
Regex.Matches(source, "ContentTemplate=\"\\{TemplateBinding EffectiveLogoPresenterContentTemplate\\}\"")
|
||||
.Count
|
||||
.ShouldBe(3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -236,8 +245,11 @@ public class WindowTitleBarLogoVisibilityTests
|
||||
|
||||
foreach (var source in new[] { fullscreenPopoverSource, drawnDecorationsSource })
|
||||
{
|
||||
source.ShouldContain("Content=\"{Binding $parent[atom:Window].EffectiveLogo}\"");
|
||||
source.ShouldContain("Content=\"{Binding $parent[atom:Window].EffectiveFullscreenLogo}\"");
|
||||
source.ShouldContain(
|
||||
"ContentTemplate=\"{Binding $parent[atom:Window].EffectiveFullscreenLogoTemplate}\"");
|
||||
source.ShouldNotContain("Content=\"{Binding $parent[atom:Window].EffectiveLogo}\"");
|
||||
source.ShouldNotContain(
|
||||
"ContentTemplate=\"{Binding $parent[atom:Window].EffectiveLogoTemplate}\"");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user