mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 11:56:30 +00:00
Core - Streamlined public parts of profile creation
UI - Started adjusting the VMs for the layer refactor
This commit is contained in:
1 parent
12ac50226f
commit
3e75f200f4
58 files changed
+694
-1196
No files matched your search
+4
-25
@@ -1,44 +1,23 @@
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract
|
||||
{
|
||||
public abstract class DisplayConditionViewModel : PropertyChangedBase, IDisposable
|
||||
public abstract class DisplayConditionViewModel : Conductor<DisplayConditionViewModel>.Collection.AllActive
|
||||
{
|
||||
protected DisplayConditionViewModel(DisplayConditionPart model, DisplayConditionViewModel parent)
|
||||
protected DisplayConditionViewModel(DisplayConditionPart model)
|
||||
{
|
||||
Model = model;
|
||||
Parent = parent;
|
||||
Children = new BindableCollection<DisplayConditionViewModel>();
|
||||
}
|
||||
|
||||
public DisplayConditionPart Model { get; }
|
||||
public DisplayConditionViewModel Parent { get; set; }
|
||||
public BindableCollection<DisplayConditionViewModel> Children { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var child in Children)
|
||||
child.Dispose();
|
||||
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public abstract void Update();
|
||||
|
||||
public virtual void Delete()
|
||||
{
|
||||
Model.Parent.RemoveChild(Model);
|
||||
Parent.Update();
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
((DisplayConditionViewModel) Parent).Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -124,7 +124,7 @@
|
||||
<materialDesign:PackIcon Kind="Add" Width="18" Height="18" />
|
||||
</Button>
|
||||
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Children}">
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<materialDesign:TransitioningContent>
|
||||
|
||||
+16
-24
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract;
|
||||
@@ -11,21 +10,24 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
{
|
||||
public class DisplayConditionGroupViewModel : DisplayConditionViewModel, IViewAware
|
||||
public class DisplayConditionGroupViewModel : DisplayConditionViewModel
|
||||
{
|
||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private bool _isInitialized;
|
||||
private bool _isRootGroup;
|
||||
|
||||
public DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup, DisplayConditionViewModel parent, bool isListGroup,
|
||||
IProfileEditorService profileEditorService, IDisplayConditionsVmFactory displayConditionsVmFactory) : base(displayConditionGroup, parent)
|
||||
public DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup,
|
||||
bool isListGroup,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDisplayConditionsVmFactory displayConditionsVmFactory)
|
||||
: base(displayConditionGroup)
|
||||
{
|
||||
IsListGroup = isListGroup;
|
||||
_profileEditorService = profileEditorService;
|
||||
_displayConditionsVmFactory = displayConditionsVmFactory;
|
||||
|
||||
Children.CollectionChanged += (sender, args) => NotifyOfPropertyChange(nameof(DisplayBooleanOperator));
|
||||
Items.CollectionChanged += (sender, args) => NotifyOfPropertyChange(nameof(DisplayBooleanOperator));
|
||||
|
||||
Execute.PostToUIThread(async () =>
|
||||
{
|
||||
@@ -50,16 +52,9 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
set => SetAndNotify(ref _isInitialized, value);
|
||||
}
|
||||
|
||||
public bool DisplayBooleanOperator => Children.Count > 1;
|
||||
public bool DisplayBooleanOperator => Items.Count > 1;
|
||||
public string SelectedBooleanOperator => DisplayConditionGroup.BooleanOperator.Humanize();
|
||||
|
||||
public void AttachView(UIElement view)
|
||||
{
|
||||
View = view;
|
||||
}
|
||||
|
||||
public UIElement View { get; set; }
|
||||
|
||||
public void SelectBooleanOperator(string type)
|
||||
{
|
||||
var enumValue = Enum.Parse<BooleanOperator>(type);
|
||||
@@ -105,39 +100,36 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
NotifyOfPropertyChange(nameof(SelectedBooleanOperator));
|
||||
|
||||
// Remove VMs of effects no longer applied on the layer
|
||||
var toRemove = Children.Where(c => !DisplayConditionGroup.Children.Contains(c.Model)).ToList();
|
||||
var toRemove = Items.Where(c => !DisplayConditionGroup.Children.Contains(c.Model)).ToList();
|
||||
// Using RemoveRange breaks our lovely animations
|
||||
foreach (var displayConditionViewModel in toRemove)
|
||||
{
|
||||
Children.Remove(displayConditionViewModel);
|
||||
displayConditionViewModel.Dispose();
|
||||
}
|
||||
CloseItem(displayConditionViewModel);
|
||||
|
||||
foreach (var childModel in Model.Children)
|
||||
{
|
||||
if (Children.Any(c => c.Model == childModel))
|
||||
if (Items.Any(c => c.Model == childModel))
|
||||
continue;
|
||||
|
||||
switch (childModel)
|
||||
{
|
||||
case DisplayConditionGroup displayConditionGroup:
|
||||
Children.Add(_displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, this, IsListGroup));
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, IsListGroup));
|
||||
break;
|
||||
case DisplayConditionList displayConditionListPredicate:
|
||||
Children.Add(_displayConditionsVmFactory.DisplayConditionListViewModel(displayConditionListPredicate, this));
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionListViewModel(displayConditionListPredicate));
|
||||
break;
|
||||
case DisplayConditionPredicate displayConditionPredicate:
|
||||
if (!IsListGroup)
|
||||
Children.Add(_displayConditionsVmFactory.DisplayConditionPredicateViewModel(displayConditionPredicate, this));
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionPredicateViewModel(displayConditionPredicate));
|
||||
break;
|
||||
case DisplayConditionListPredicate displayConditionListPredicate:
|
||||
if (IsListGroup)
|
||||
Children.Add(_displayConditionsVmFactory.DisplayConditionListPredicateViewModel(displayConditionListPredicate, this));
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionListPredicateViewModel(displayConditionListPredicate));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var childViewModel in Children)
|
||||
foreach (var childViewModel in Items)
|
||||
childViewModel.Update();
|
||||
}
|
||||
}
|
||||
|
||||
+12
-13
@@ -17,9 +17,9 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
{
|
||||
public class DisplayConditionListPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>
|
||||
public class DisplayConditionListPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>, IDisposable
|
||||
{
|
||||
private readonly IDataModelService _dataModelService;
|
||||
private readonly IConditionOperatorService _conditionOperatorService;
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
@@ -39,16 +39,15 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
|
||||
public DisplayConditionListPredicateViewModel(
|
||||
DisplayConditionListPredicate displayConditionListPredicate,
|
||||
DisplayConditionViewModel parent,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDataModelUIService dataModelUIService,
|
||||
IDataModelService dataModelService,
|
||||
IConditionOperatorService conditionOperatorService,
|
||||
ISettingsService settingsService,
|
||||
IEventAggregator eventAggregator) : base(displayConditionListPredicate, parent)
|
||||
IEventAggregator eventAggregator) : base(displayConditionListPredicate)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_dataModelUIService = dataModelUIService;
|
||||
_dataModelService = dataModelService;
|
||||
_conditionOperatorService = conditionOperatorService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_updateTimer = new Timer(500);
|
||||
_supportedInputTypes = new List<Type>();
|
||||
@@ -206,7 +205,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
|
||||
// Get the supported operators
|
||||
Operators.Clear();
|
||||
Operators.AddRange(_dataModelService.GetConditionOperatorsForType(leftSideType));
|
||||
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
||||
if (DisplayConditionListPredicate.Operator == null)
|
||||
DisplayConditionListPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
||||
SelectedOperator = DisplayConditionListPredicate.Operator;
|
||||
@@ -277,12 +276,6 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
_eventAggregator.Subscribe(this);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_updateTimer.Stop();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
|
||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (LeftSideDataModelOpen)
|
||||
@@ -353,5 +346,11 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
SelectedOperator = displayConditionOperator;
|
||||
ApplyOperator();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_updateTimer.Dispose();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -105,7 +105,7 @@
|
||||
</Button.ContextMenu>
|
||||
</Button>
|
||||
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Children}" Margin="0 4 0 0">
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items}" Margin="0 4 0 0">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<materialDesign:TransitioningContent>
|
||||
|
||||
+14
-17
@@ -14,7 +14,7 @@ using Humanizer;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
{
|
||||
public class DisplayConditionListViewModel : DisplayConditionViewModel
|
||||
public class DisplayConditionListViewModel : DisplayConditionViewModel, IDisposable
|
||||
{
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
||||
@@ -30,7 +30,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
IProfileEditorService profileEditorService,
|
||||
IDataModelUIService dataModelUIService,
|
||||
IDisplayConditionsVmFactory displayConditionsVmFactory,
|
||||
ISettingsService settingsService) : base(displayConditionList, parent)
|
||||
ISettingsService settingsService) : base(displayConditionList)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_dataModelUIService = dataModelUIService;
|
||||
@@ -152,36 +152,27 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
TargetDataModel.ApplyTypeFilter(true, typeof(IList));
|
||||
|
||||
// Remove VMs of effects no longer applied on the layer
|
||||
var toRemove = Children.Where(c => !DisplayConditionList.Children.Contains(c.Model)).ToList();
|
||||
var toRemove = Items.Where(c => !DisplayConditionList.Children.Contains(c.Model)).ToList();
|
||||
// Using RemoveRange breaks our lovely animations
|
||||
foreach (var displayConditionViewModel in toRemove)
|
||||
{
|
||||
Children.Remove(displayConditionViewModel);
|
||||
displayConditionViewModel.Dispose();
|
||||
}
|
||||
CloseItem(displayConditionViewModel);
|
||||
|
||||
foreach (var childModel in Model.Children)
|
||||
{
|
||||
if (Children.Any(c => c.Model == childModel))
|
||||
if (Items.Any(c => c.Model == childModel))
|
||||
continue;
|
||||
if (!(childModel is DisplayConditionGroup displayConditionGroup))
|
||||
continue;
|
||||
|
||||
var viewModel = _displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, this, true);
|
||||
var viewModel = _displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, true);
|
||||
viewModel.IsRootGroup = true;
|
||||
Children.Add(viewModel);
|
||||
ActivateItem(viewModel);
|
||||
}
|
||||
|
||||
foreach (var childViewModel in Children)
|
||||
foreach (var childViewModel in Items)
|
||||
childViewModel.Update();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_updateTimer.Stop();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
|
||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (TargetDataModelOpen)
|
||||
@@ -205,5 +196,11 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
SelectedListProperty = dataModelListViewModel;
|
||||
ApplyList();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_updateTimer.Dispose();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-14
@@ -16,9 +16,9 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
{
|
||||
public class DisplayConditionPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>
|
||||
public class DisplayConditionPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>, IDisposable
|
||||
{
|
||||
private readonly IDataModelService _dataModelService;
|
||||
private readonly IConditionOperatorService _conditionOperatorService;
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
@@ -38,16 +38,15 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
|
||||
public DisplayConditionPredicateViewModel(
|
||||
DisplayConditionPredicate displayConditionPredicate,
|
||||
DisplayConditionViewModel parent,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDataModelUIService dataModelUIService,
|
||||
IDataModelService dataModelService,
|
||||
IConditionOperatorService conditionOperatorService,
|
||||
ISettingsService settingsService,
|
||||
IEventAggregator eventAggregator) : base(displayConditionPredicate, parent)
|
||||
IEventAggregator eventAggregator) : base(displayConditionPredicate)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_dataModelUIService = dataModelUIService;
|
||||
_dataModelService = dataModelService;
|
||||
_conditionOperatorService = conditionOperatorService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_updateTimer = new Timer(500);
|
||||
_supportedInputTypes = new List<Type>();
|
||||
@@ -208,7 +207,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
|
||||
// Get the supported operators
|
||||
Operators.Clear();
|
||||
Operators.AddRange(_dataModelService.GetConditionOperatorsForType(leftSideType));
|
||||
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
||||
if (DisplayConditionPredicate.Operator == null)
|
||||
DisplayConditionPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
||||
SelectedOperator = DisplayConditionPredicate.Operator;
|
||||
@@ -278,13 +277,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
);
|
||||
_eventAggregator.Subscribe(this);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_updateTimer.Stop();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
|
||||
|
||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (LeftSideDataModelOpen)
|
||||
@@ -335,5 +328,11 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
SelectedOperator = displayConditionOperator;
|
||||
ApplyOperator();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_updateTimer.Dispose();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
<Grid Grid.Row="2" Grid.Column="0">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Background="{StaticResource MaterialDesignCardBackground}">
|
||||
<ContentControl s:View.Model="{Binding RootGroup}" />
|
||||
<ContentControl s:View.Model="{Binding ActiveItem}" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
|
||||
+7
-17
@@ -3,17 +3,17 @@ using Artemis.Core;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
{
|
||||
public class DisplayConditionsViewModel : ProfileEditorPanelViewModel
|
||||
public class DisplayConditionsViewModel : Conductor<DisplayConditionGroupViewModel>, IProfileEditorPanelViewModel
|
||||
{
|
||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private bool _alwaysFinishTimeline;
|
||||
private bool _displayContinuously;
|
||||
private RenderProfileElement _renderProfileElement;
|
||||
private DisplayConditionGroupViewModel _rootGroup;
|
||||
private int _transitionerIndex;
|
||||
|
||||
public DisplayConditionsViewModel(IProfileEditorService profileEditorService, IDisplayConditionsVmFactory displayConditionsVmFactory)
|
||||
@@ -28,11 +28,6 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
set => SetAndNotify(ref _transitionerIndex, value);
|
||||
}
|
||||
|
||||
public DisplayConditionGroupViewModel RootGroup
|
||||
{
|
||||
get => _rootGroup;
|
||||
set => SetAndNotify(ref _rootGroup, value);
|
||||
}
|
||||
|
||||
public RenderProfileElement RenderProfileElement
|
||||
{
|
||||
@@ -70,9 +65,6 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
protected override void OnDeactivate()
|
||||
{
|
||||
_profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected;
|
||||
|
||||
RootGroup?.Dispose();
|
||||
RootGroup = null;
|
||||
}
|
||||
|
||||
private void ProfileEditorServiceOnProfileElementSelected(object sender, RenderProfileElementEventArgs e)
|
||||
@@ -87,8 +79,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
|
||||
if (e.RenderProfileElement == null)
|
||||
{
|
||||
RootGroup?.Dispose();
|
||||
RootGroup = null;
|
||||
ActiveItem = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,14 +87,13 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
if (e.RenderProfileElement.DisplayConditionGroup == null)
|
||||
e.RenderProfileElement.DisplayConditionGroup = new DisplayConditionGroup(null);
|
||||
|
||||
RootGroup?.Dispose();
|
||||
RootGroup = _displayConditionsVmFactory.DisplayConditionGroupViewModel(e.RenderProfileElement.DisplayConditionGroup, null, false);
|
||||
RootGroup.IsRootGroup = true;
|
||||
RootGroup.Update();
|
||||
ActiveItem = _displayConditionsVmFactory.DisplayConditionGroupViewModel(e.RenderProfileElement.DisplayConditionGroup, false);
|
||||
ActiveItem.IsRootGroup = true;
|
||||
ActiveItem.Update();
|
||||
|
||||
// Only show the intro to conditions once, and only if the layer has no conditions
|
||||
if (TransitionerIndex != 1)
|
||||
TransitionerIndex = RootGroup.Children.Any() ? 1 : 0;
|
||||
TransitionerIndex = ActiveItem.Items.Any() ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user