mirror of
https://github.com/Stone-Red-Code/DesktopMagic.git
synced 2026-09-04 08:56:15 +02:00
- Add ComboBox element to the API
This commit is contained in:
@@ -17,9 +17,11 @@ namespace DesktopMagic.BuiltInWindowElements
|
|||||||
private volatile bool calculate = true;
|
private volatile bool calculate = true;
|
||||||
private Bitmap output = new Bitmap(880, 300);
|
private Bitmap output = new Bitmap(880, 300);
|
||||||
|
|
||||||
|
public override int UpdateInterval => 0;
|
||||||
|
|
||||||
public override void Start()
|
public override void Start()
|
||||||
{
|
{
|
||||||
sampleAggregator.FftCalculated += new EventHandler<FftEventArgs>(FftCalculated);
|
sampleAggregator.FftCalculated += FftCalculated;
|
||||||
sampleAggregator.PerformFFT = true;
|
sampleAggregator.PerformFFT = true;
|
||||||
|
|
||||||
waveIn = new WasapiLoopbackCapture();
|
waveIn = new WasapiLoopbackCapture();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using DesktopMagicPluginAPI;
|
using DesktopMagicPluginAPI;
|
||||||
using DesktopMagicPluginAPI.Drawing;
|
using DesktopMagicPluginAPI.Drawing;
|
||||||
|
using DesktopMagicPluginAPI.Inputs;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
@@ -9,11 +10,14 @@ namespace DesktopMagic.BuiltInWindowElements
|
|||||||
{
|
{
|
||||||
internal class TimePlugin : Plugin
|
internal class TimePlugin : Plugin
|
||||||
{
|
{
|
||||||
|
[Element("Display Seconds:")]
|
||||||
|
private CheckBox checkBox = new CheckBox(true);
|
||||||
|
|
||||||
public override int UpdateInterval => 1000;
|
public override int UpdateInterval => 1000;
|
||||||
|
|
||||||
public override Bitmap Main()
|
public override Bitmap Main()
|
||||||
{
|
{
|
||||||
string time = DateTime.Now.ToLongTimeString();
|
string time = checkBox.Value ? DateTime.Now.ToLongTimeString() : DateTime.Now.ToShortTimeString();
|
||||||
|
|
||||||
Font font = new Font(Application.Theme.Font, 200);
|
Font font = new Font(Application.Theme.Font, 200);
|
||||||
|
|
||||||
@@ -36,7 +40,7 @@ namespace DesktopMagic.BuiltInWindowElements
|
|||||||
|
|
||||||
private SizeF CalculateSize(Graphics graphics, Font font)
|
private SizeF CalculateSize(Graphics graphics, Font font)
|
||||||
{
|
{
|
||||||
string template = "##:##:##";
|
string template = checkBox.Value ? "##:##:##" : "##:##";
|
||||||
SizeF size = new SizeF();
|
SizeF size = new SizeF();
|
||||||
for (int i = 0; i < 9; i++)
|
for (int i = 0; i < 9; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
using Google.Apis.Auth.OAuth2;
|
|
||||||
using Google.Apis.Calendar.v3;
|
|
||||||
using Google.Apis.Calendar.v3.Data;
|
|
||||||
using Google.Apis.Services;
|
|
||||||
using Google.Apis.Util.Store;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace DesktopMagic
|
|
||||||
{
|
|
||||||
internal class CalendarManagment
|
|
||||||
{
|
|
||||||
private static string[] Scopes = { CalendarService.Scope.CalendarReadonly };
|
|
||||||
|
|
||||||
private static string ApplicationName = "Google Calendar API .NET " + App.AppName;
|
|
||||||
|
|
||||||
[Obsolete]
|
|
||||||
public (List<string>, List<string>) GetEvents()
|
|
||||||
{
|
|
||||||
List<string> upcomingEventNames = new List<string>();
|
|
||||||
List<string> upcomingEventTimes = new List<string>();
|
|
||||||
UserCredential credential;
|
|
||||||
|
|
||||||
if (!File.Exists("credentials.json"))
|
|
||||||
{
|
|
||||||
return (new(), new());
|
|
||||||
}
|
|
||||||
|
|
||||||
using (FileStream stream = new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
|
|
||||||
{
|
|
||||||
// The file token.json stores the user's access and refresh tokens, and is created
|
|
||||||
// automatically when the authorization flow completes for the first time.
|
|
||||||
string credPath = "token.json";
|
|
||||||
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
|
|
||||||
GoogleClientSecrets.Load(stream).Secrets,
|
|
||||||
Scopes,
|
|
||||||
"user",
|
|
||||||
CancellationToken.None,
|
|
||||||
new FileDataStore(credPath, true)).Result;
|
|
||||||
Debug.WriteLine("Credential file saved to: " + credPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Google Calendar API service.
|
|
||||||
CalendarService service = new CalendarService(new BaseClientService.Initializer()
|
|
||||||
{
|
|
||||||
HttpClientInitializer = credential,
|
|
||||||
ApplicationName = ApplicationName,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Define parameters of request.
|
|
||||||
EventsResource.ListRequest request = service.Events.List("primary");
|
|
||||||
request.TimeMin = DateTime.Now;
|
|
||||||
request.ShowDeleted = false;
|
|
||||||
request.SingleEvents = true;
|
|
||||||
request.MaxResults = 10;
|
|
||||||
request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime;
|
|
||||||
|
|
||||||
// List events.
|
|
||||||
Events events = request.Execute();
|
|
||||||
if (events.Items != null && events.Items.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (Event eventItem in events.Items)
|
|
||||||
{
|
|
||||||
if (upcomingEventNames.Count < 10)
|
|
||||||
{
|
|
||||||
string when = eventItem.Start.DateTime.ToString();
|
|
||||||
if (string.IsNullOrEmpty(when))
|
|
||||||
{
|
|
||||||
when = eventItem.Start.Date;
|
|
||||||
}
|
|
||||||
upcomingEventNames.Add(eventItem.Summary);
|
|
||||||
upcomingEventTimes.Add(when);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (upcomingEventNames, upcomingEventTimes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class CalendarItems
|
|
||||||
{
|
|
||||||
public string Eventname { get; set; }
|
|
||||||
public string DateTime { get; set; }
|
|
||||||
public string Font { get; set; }
|
|
||||||
public string Color { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -193,6 +193,36 @@ namespace DesktopMagic.Helpers
|
|||||||
|
|
||||||
_ = dockPanel.Children.Add(slider);
|
_ = dockPanel.Children.Add(slider);
|
||||||
}
|
}
|
||||||
|
else if (settingElement.Element is DesktopMagicPluginAPI.Inputs.ComboBox eComboBox)
|
||||||
|
{
|
||||||
|
ComboBox comboBox = new()
|
||||||
|
{
|
||||||
|
ItemsSource = eComboBox.Items,
|
||||||
|
IsEditable = false,
|
||||||
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||||
|
SelectedIndex = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
comboBox.SelectionChanged += (_s, _e) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
eComboBox.Value = comboBox.Text;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
DisplayException(ex.Message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
eComboBox.OnValueChanged += () =>
|
||||||
|
{
|
||||||
|
comboBox.SelectedItem = eComboBox.Value;
|
||||||
|
};
|
||||||
|
|
||||||
|
_ = dockPanel.Children.Add(comboBox);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisplayException(string message)
|
private void DisplayException(string message)
|
||||||
@@ -201,7 +231,7 @@ namespace DesktopMagic.Helpers
|
|||||||
_ = MessageBox.Show("File execution error:\n" + message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
_ = MessageBox.Show("File execution error:\n" + message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
int index = MainWindow.WindowNames.IndexOf(optionsComboBox.SelectedItem.ToString());
|
int index = MainWindow.WindowNames.IndexOf(optionsComboBox.SelectedItem.ToString());
|
||||||
|
|
||||||
PluginWindow window = MainWindow.Windows[index] as PluginWindow;
|
PluginWindow window = MainWindow.Windows[index];
|
||||||
window?.Exit();
|
window?.Exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,11 +206,11 @@ namespace DesktopMagic
|
|||||||
switch (checkBox.Name)
|
switch (checkBox.Name)
|
||||||
{
|
{
|
||||||
case "TimeCb":
|
case "TimeCb":
|
||||||
window = new PluginWindow(new TimePlugin());
|
window = new PluginWindow(new TimePlugin(), checkBox.Content.ToString());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "DateCb":
|
case "DateCb":
|
||||||
window = new PluginWindow(new DatePlugin());
|
window = new PluginWindow(new DatePlugin(), checkBox.Content.ToString());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "CpuUsageCb":
|
case "CpuUsageCb":
|
||||||
@@ -218,7 +218,7 @@ namespace DesktopMagic
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "MusicVisualizerCb":
|
case "MusicVisualizerCb":
|
||||||
window = new PluginWindow(new MusicVisualizerPlugin());
|
window = new PluginWindow(new MusicVisualizerPlugin(), checkBox.Content.ToString());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -285,7 +285,6 @@ namespace DesktopMagic
|
|||||||
|
|
||||||
Windows.RemoveAt(index);
|
Windows.RemoveAt(index);
|
||||||
WindowNames.RemoveAt(index);
|
WindowNames.RemoveAt(index);
|
||||||
//window.Close();
|
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace DesktopMagic
|
|||||||
Width = double.Parse(key.GetValue(pluginName + "WindowWidth", 500).ToString());
|
Width = double.Parse(key.GetValue(pluginName + "WindowWidth", 500).ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginWindow(Plugin pluginClassInstance) : this(pluginClassInstance.GetType().Name)
|
public PluginWindow(Plugin pluginClassInstance, string pluginName) : this(pluginName)
|
||||||
{
|
{
|
||||||
this.pluginClassInstance = pluginClassInstance;
|
this.pluginClassInstance = pluginClassInstance;
|
||||||
}
|
}
|
||||||
@@ -125,8 +125,8 @@ namespace DesktopMagic
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
viewBox.Margin = new Thickness(MainWindow.Theme.Margin);
|
viewBox.Margin = new Thickness(MainWindow.Theme.Margin);
|
||||||
border.Width = viewBox.ActualWidth + MainWindow.Theme.Margin * 2;
|
border.Width = viewBox.ActualWidth + (MainWindow.Theme.Margin * 2);
|
||||||
border.Height = viewBox.ActualHeight + MainWindow.Theme.Margin * 2;
|
border.Height = viewBox.ActualHeight + (MainWindow.Theme.Margin * 2);
|
||||||
rectangleGeometry.Rect = new Rect(-MainWindow.Theme.Margin, -MainWindow.Theme.Margin, border.ActualWidth, border.ActualHeight);
|
rectangleGeometry.Rect = new Rect(-MainWindow.Theme.Margin, -MainWindow.Theme.Margin, border.ActualWidth, border.ActualHeight);
|
||||||
border.Background = MainWindow.Theme.BackgroundBrush;
|
border.Background = MainWindow.Theme.BackgroundBrush;
|
||||||
border.CornerRadius = new CornerRadius(MainWindow.Theme.CornerRadius);
|
border.CornerRadius = new CornerRadius(MainWindow.Theme.CornerRadius);
|
||||||
|
|||||||
@@ -10,6 +10,10 @@
|
|||||||
- [CheckBox](#T-DesktopMagicPluginAPI-Inputs-CheckBox 'DesktopMagicPluginAPI.Inputs.CheckBox')
|
- [CheckBox](#T-DesktopMagicPluginAPI-Inputs-CheckBox 'DesktopMagicPluginAPI.Inputs.CheckBox')
|
||||||
- [#ctor(value)](#M-DesktopMagicPluginAPI-Inputs-CheckBox-#ctor-System-Boolean- 'DesktopMagicPluginAPI.Inputs.CheckBox.#ctor(System.Boolean)')
|
- [#ctor(value)](#M-DesktopMagicPluginAPI-Inputs-CheckBox-#ctor-System-Boolean- 'DesktopMagicPluginAPI.Inputs.CheckBox.#ctor(System.Boolean)')
|
||||||
- [Value](#P-DesktopMagicPluginAPI-Inputs-CheckBox-Value 'DesktopMagicPluginAPI.Inputs.CheckBox.Value')
|
- [Value](#P-DesktopMagicPluginAPI-Inputs-CheckBox-Value 'DesktopMagicPluginAPI.Inputs.CheckBox.Value')
|
||||||
|
- [ComboBox](#T-DesktopMagicPluginAPI-Inputs-ComboBox 'DesktopMagicPluginAPI.Inputs.ComboBox')
|
||||||
|
- [#ctor(items)](#M-DesktopMagicPluginAPI-Inputs-ComboBox-#ctor-System-String[]- 'DesktopMagicPluginAPI.Inputs.ComboBox.#ctor(System.String[])')
|
||||||
|
- [Items](#P-DesktopMagicPluginAPI-Inputs-ComboBox-Items 'DesktopMagicPluginAPI.Inputs.ComboBox.Items')
|
||||||
|
- [Value](#P-DesktopMagicPluginAPI-Inputs-ComboBox-Value 'DesktopMagicPluginAPI.Inputs.ComboBox.Value')
|
||||||
- [Element](#T-DesktopMagicPluginAPI-Inputs-Element 'DesktopMagicPluginAPI.Inputs.Element')
|
- [Element](#T-DesktopMagicPluginAPI-Inputs-Element 'DesktopMagicPluginAPI.Inputs.Element')
|
||||||
- [ValueChanged()](#M-DesktopMagicPluginAPI-Inputs-Element-ValueChanged 'DesktopMagicPluginAPI.Inputs.Element.ValueChanged')
|
- [ValueChanged()](#M-DesktopMagicPluginAPI-Inputs-Element-ValueChanged 'DesktopMagicPluginAPI.Inputs.Element.ValueChanged')
|
||||||
- [ElementAttribute](#T-DesktopMagicPluginAPI-Inputs-ElementAttribute 'DesktopMagicPluginAPI.Inputs.ElementAttribute')
|
- [ElementAttribute](#T-DesktopMagicPluginAPI-Inputs-ElementAttribute 'DesktopMagicPluginAPI.Inputs.ElementAttribute')
|
||||||
@@ -151,6 +155,48 @@ Initializes a new instance of the [CheckBox](#T-DesktopMagicPluginAPI-Inputs-Che
|
|||||||
|
|
||||||
Gets or set a value indicating whether the [CheckBox](#T-DesktopMagicPluginAPI-Inputs-CheckBox 'DesktopMagicPluginAPI.Inputs.CheckBox') is in the checked state.
|
Gets or set a value indicating whether the [CheckBox](#T-DesktopMagicPluginAPI-Inputs-CheckBox 'DesktopMagicPluginAPI.Inputs.CheckBox') is in the checked state.
|
||||||
|
|
||||||
|
<a name='T-DesktopMagicPluginAPI-Inputs-ComboBox'></a>
|
||||||
|
## ComboBox `type`
|
||||||
|
|
||||||
|
##### Namespace
|
||||||
|
|
||||||
|
DesktopMagicPluginAPI.Inputs
|
||||||
|
|
||||||
|
##### Summary
|
||||||
|
|
||||||
|
Represents a selection control with a drop-down list.
|
||||||
|
|
||||||
|
<a name='M-DesktopMagicPluginAPI-Inputs-ComboBox-#ctor-System-String[]-'></a>
|
||||||
|
### #ctor(items) `constructor`
|
||||||
|
|
||||||
|
##### Summary
|
||||||
|
|
||||||
|
Initializes a new instance of the [Label](#T-DesktopMagicPluginAPI-Inputs-Label 'DesktopMagicPluginAPI.Inputs.Label') class with the provided `items`.
|
||||||
|
|
||||||
|
##### Parameters
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| items | [System.String[]](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.String[] 'System.String[]') | |
|
||||||
|
|
||||||
|
<a name='P-DesktopMagicPluginAPI-Inputs-ComboBox-Items'></a>
|
||||||
|
### Items `property`
|
||||||
|
|
||||||
|
##### Summary
|
||||||
|
|
||||||
|
Gets the collection used to generate the content of the [ComboBox](#T-DesktopMagicPluginAPI-Inputs-ComboBox 'DesktopMagicPluginAPI.Inputs.ComboBox').
|
||||||
|
|
||||||
|
<a name='P-DesktopMagicPluginAPI-Inputs-ComboBox-Value'></a>
|
||||||
|
### Value `property`
|
||||||
|
|
||||||
|
##### Summary
|
||||||
|
|
||||||
|
Gets the currently selected item associated with this [ComboBox](#T-DesktopMagicPluginAPI-Inputs-ComboBox 'DesktopMagicPluginAPI.Inputs.ComboBox').
|
||||||
|
|
||||||
|
##### Remarks
|
||||||
|
|
||||||
|
If you assign a value to this property, the displayed text in the user interface will not be changed.
|
||||||
|
|
||||||
<a name='T-DesktopMagicPluginAPI-Inputs-Element'></a>
|
<a name='T-DesktopMagicPluginAPI-Inputs-Element'></a>
|
||||||
## Element `type`
|
## Element `type`
|
||||||
|
|
||||||
|
|||||||
@@ -145,6 +145,28 @@
|
|||||||
</summary>
|
</summary>
|
||||||
<param name="value">A value indicating whether the <see cref="T:DesktopMagicPluginAPI.Inputs.CheckBox"/> is in the checked state.</param>
|
<param name="value">A value indicating whether the <see cref="T:DesktopMagicPluginAPI.Inputs.CheckBox"/> is in the checked state.</param>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="T:DesktopMagicPluginAPI.Inputs.ComboBox">
|
||||||
|
<summary>
|
||||||
|
Represents a selection control with a drop-down list.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:DesktopMagicPluginAPI.Inputs.ComboBox.Items">
|
||||||
|
<summary>
|
||||||
|
Gets the collection used to generate the content of the <see cref="T:DesktopMagicPluginAPI.Inputs.ComboBox"/>.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:DesktopMagicPluginAPI.Inputs.ComboBox.Value">
|
||||||
|
<summary>
|
||||||
|
Gets the currently selected item associated with this <see cref="T:DesktopMagicPluginAPI.Inputs.ComboBox"/>.
|
||||||
|
</summary>
|
||||||
|
<remarks>If you assign a value to this property, the displayed text in the user interface will not be changed.</remarks>
|
||||||
|
</member>
|
||||||
|
<member name="M:DesktopMagicPluginAPI.Inputs.ComboBox.#ctor(System.String[])">
|
||||||
|
<summary>
|
||||||
|
Initializes a new instance of the <see cref="T:DesktopMagicPluginAPI.Inputs.Label"/> class with the provided <paramref name="items"/>.
|
||||||
|
</summary>
|
||||||
|
<param name="items"></param>
|
||||||
|
</member>
|
||||||
<member name="T:DesktopMagicPluginAPI.Inputs.Element">
|
<member name="T:DesktopMagicPluginAPI.Inputs.Element">
|
||||||
<summary>
|
<summary>
|
||||||
The element base class.
|
The element base class.
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace DesktopMagicPluginAPI.Inputs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a selection control with a drop-down list.
|
||||||
|
/// </summary>
|
||||||
|
public class ComboBox : Element
|
||||||
|
{
|
||||||
|
private string _value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the collection used to generate the content of the <see cref="ComboBox"/>.
|
||||||
|
/// </summary>
|
||||||
|
public ObservableCollection<string> Items { get; } = new ObservableCollection<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the currently selected item associated with this <see cref="ComboBox"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>If you assign a value to this property, the displayed text in the user interface will not be changed.</remarks>
|
||||||
|
public string Value
|
||||||
|
{
|
||||||
|
get => _value;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_value != value)
|
||||||
|
{
|
||||||
|
_value = value;
|
||||||
|
ValueChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Label"/> class with the provided <paramref name="items"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
public ComboBox(params string[] items)
|
||||||
|
{
|
||||||
|
foreach (string item in items)
|
||||||
|
{
|
||||||
|
Items.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,17 +19,7 @@ namespace DesktopMagicPluginAPI
|
|||||||
public IPluginData Application
|
public IPluginData Application
|
||||||
{
|
{
|
||||||
get => application;
|
get => application;
|
||||||
set
|
set => application = application is null ? value : throw new InvalidOperationException($"You cannot set the value of the {nameof(Application)} property");
|
||||||
{
|
|
||||||
if (application is null)
|
|
||||||
{
|
|
||||||
application = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"You cannot set the value of the {nameof(Application)} property");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user