mirror of
https://github.com/ckaczor/FloatingStatusWindow.git
synced 2026-03-10 19:48:48 -04:00
Add template project
This commit is contained in:
21
Template/SettingsWindow/AboutSettingsPanel.xaml
Normal file
21
Template/SettingsWindow/AboutSettingsPanel.xaml
Normal file
@@ -0,0 +1,21 @@
|
||||
<windows:CategoryPanelBase x:Class="Template.SettingsWindow.AboutSettingsPanel"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:properties="clr-namespace:Template.Properties"
|
||||
xmlns:windows="clr-namespace:ChrisKaczor.Wpf.Windows;assembly=ChrisKaczor.Wpf.Windows.CategoryWindow"
|
||||
xmlns:template="clr-namespace:Template"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="150"
|
||||
d:DesignWidth="300">
|
||||
<Grid>
|
||||
<StackPanel windows:Spacing.Vertical="10">
|
||||
<TextBlock Text="{x:Static properties:Resources.ApplicationName}"
|
||||
FontWeight="Bold" />
|
||||
<TextBlock Text="{Binding Source={x:Static template:UpdateCheck.LocalVersion}, StringFormat={x:Static properties:Resources.Version}}"
|
||||
Name="VersionLabel" />
|
||||
<TextBlock Text="User" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</windows:CategoryPanelBase>
|
||||
12
Template/SettingsWindow/AboutSettingsPanel.xaml.cs
Normal file
12
Template/SettingsWindow/AboutSettingsPanel.xaml.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace Template.SettingsWindow
|
||||
{
|
||||
public partial class AboutSettingsPanel
|
||||
{
|
||||
public AboutSettingsPanel()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public override string CategoryName => Properties.Resources.optionCategoryAbout;
|
||||
}
|
||||
}
|
||||
16
Template/SettingsWindow/GeneralSettingsPanel.xaml
Normal file
16
Template/SettingsWindow/GeneralSettingsPanel.xaml
Normal file
@@ -0,0 +1,16 @@
|
||||
<windows:CategoryPanelBase x:Class="Template.SettingsWindow.GeneralSettingsPanel"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:properties="clr-namespace:Template.Properties"
|
||||
xmlns:windows="clr-namespace:ChrisKaczor.Wpf.Windows;assembly=ChrisKaczor.Wpf.Windows.CategoryWindow"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="300">
|
||||
<StackPanel windows:Spacing.Vertical="10">
|
||||
<CheckBox Content="{x:Static properties:Resources.startWithWindowsCheckBox}"
|
||||
IsChecked="{Binding Source={x:Static properties:Settings.Default}, Path=AutoStart}"
|
||||
Click="OnSaveSettings" />
|
||||
</StackPanel>
|
||||
</windows:CategoryPanelBase>
|
||||
36
Template/SettingsWindow/GeneralSettingsPanel.xaml.cs
Normal file
36
Template/SettingsWindow/GeneralSettingsPanel.xaml.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Windows;
|
||||
using ChrisKaczor.Wpf.Application;
|
||||
using Template.Properties;
|
||||
|
||||
namespace Template.SettingsWindow;
|
||||
|
||||
public partial class GeneralSettingsPanel
|
||||
{
|
||||
public GeneralSettingsPanel()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public override string CategoryName => Properties.Resources.optionCategoryGeneral;
|
||||
|
||||
public override void LoadPanel(Window parentWindow)
|
||||
{
|
||||
base.LoadPanel(parentWindow);
|
||||
|
||||
MarkLoaded();
|
||||
}
|
||||
|
||||
private void OnSaveSettings(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
private void SaveSettings()
|
||||
{
|
||||
if (!HasLoaded) return;
|
||||
|
||||
Settings.Default.Save();
|
||||
|
||||
Application.Current.SetStartWithWindows(Settings.Default.AutoStart);
|
||||
}
|
||||
}
|
||||
78
Template/SettingsWindow/ItemWindow.xaml
Normal file
78
Template/SettingsWindow/ItemWindow.xaml
Normal file
@@ -0,0 +1,78 @@
|
||||
<Window x:Class="Template.SettingsWindow.ItemWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:properties="clr-namespace:Template.Properties"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
d:DataContext="{d:DesignInstance Type=template:ItemEntry}"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
|
||||
xmlns:windows="clr-namespace:ChrisKaczor.Wpf.Windows;assembly=ChrisKaczor.Wpf.Windows.CategoryWindow"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||
xmlns:template="clr-namespace:Template"
|
||||
mc:Ignorable="d"
|
||||
Title="ItemWindow"
|
||||
ResizeMode="NoResize"
|
||||
SizeToContent="Height"
|
||||
Width="450"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Icon="/Template;component/Resources/Application.ico"
|
||||
FocusManager.FocusedElement="{Binding ElementName=NameTextBox}">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.FlatButton.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/light.cobalt.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid Margin="6">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Margin="0,4"
|
||||
windows:Spacing.Vertical="8">
|
||||
<TextBox Name="NameTextBox"
|
||||
mah:TextBoxHelper.UseFloatingWatermark="True"
|
||||
mah:TextBoxHelper.Watermark="{x:Static properties:Resources.NameColumnHeader}"
|
||||
mah:TextBoxHelper.SelectAllOnFocus="True"
|
||||
Text="{Binding Path=Name, UpdateSourceTrigger=Explicit, ValidatesOnExceptions=True}" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="0"
|
||||
Grid.Row="1"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,5,0,0"
|
||||
HorizontalAlignment="Right">
|
||||
<Button Content="{x:Static properties:Resources.OkayButton}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Width="75"
|
||||
Margin="0,0,5,0"
|
||||
IsDefault="True"
|
||||
Click="HandleOkayButtonClick">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button"
|
||||
BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Text.Length, ElementName=NameTextBox}"
|
||||
Value="0">
|
||||
<Setter Property="IsEnabled"
|
||||
Value="False" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
<Button Content="{x:Static properties:Resources.CancelButton}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Width="75"
|
||||
IsCancel="True" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
41
Template/SettingsWindow/ItemWindow.xaml.cs
Normal file
41
Template/SettingsWindow/ItemWindow.xaml.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using ChrisKaczor.Wpf.Validation;
|
||||
|
||||
namespace Template.SettingsWindow;
|
||||
|
||||
public partial class ItemWindow
|
||||
{
|
||||
public ItemWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public bool? Display(ItemEntry itemEntry, Window owner)
|
||||
{
|
||||
DataContext = itemEntry;
|
||||
|
||||
Title = string.IsNullOrWhiteSpace(itemEntry.Name) ? Properties.Resources.ItemWindowAdd : Properties.Resources.ItemWindowEdit;
|
||||
|
||||
Owner = owner;
|
||||
|
||||
return ShowDialog();
|
||||
}
|
||||
|
||||
private void HandleOkayButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!this.IsValid())
|
||||
return;
|
||||
|
||||
var item = (ItemEntry)DataContext;
|
||||
|
||||
if (!Data.ItemEntries.Contains(item))
|
||||
Data.ItemEntries.Add(item);
|
||||
|
||||
Data.Save();
|
||||
|
||||
DialogResult = true;
|
||||
|
||||
Close();
|
||||
}
|
||||
}
|
||||
90
Template/SettingsWindow/ItemsSettingsPanel.xaml
Normal file
90
Template/SettingsWindow/ItemsSettingsPanel.xaml
Normal file
@@ -0,0 +1,90 @@
|
||||
<windows:CategoryPanelBase x:Class="Template.SettingsWindow.ItemsSettingsPanel"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:properties="clr-namespace:Template.Properties"
|
||||
xmlns:windows="clr-namespace:ChrisKaczor.Wpf.Windows;assembly=ChrisKaczor.Wpf.Windows.CategoryWindow"
|
||||
xmlns:controls="clr-namespace:ChrisKaczor.Wpf.Controls;assembly=ChrisKaczor.Wpf.Controls.Link"
|
||||
xmlns:dd="urn:gong-wpf-dragdrop"
|
||||
xmlns:template="clr-namespace:Template"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="150"
|
||||
d:DesignWidth="300">
|
||||
<windows:CategoryPanelBase.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.FlatButton.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/light.cobalt.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</windows:CategoryPanelBase.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<DataGrid Name="ItemDataGrid"
|
||||
SelectionMode="Extended"
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
AutoGenerateColumns="False"
|
||||
GridLinesVisibility="None"
|
||||
CanUserResizeRows="False"
|
||||
IsReadOnly="True"
|
||||
CanUserSortColumns="False"
|
||||
SelectionUnit="FullRow"
|
||||
HeadersVisibility="Column"
|
||||
BorderThickness="1,1,1,1"
|
||||
BorderBrush="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}"
|
||||
Background="{x:Null}"
|
||||
SelectionChanged="HandleItemDataGridSelectionChanged"
|
||||
d:DataContext="{d:DesignInstance template:ItemEntry }"
|
||||
dd:DragDrop.IsDragSource="True"
|
||||
dd:DragDrop.IsDropTarget="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Binding="{Binding Path=Name}"
|
||||
Header="{x:Static properties:Resources.NameColumnHeader}"
|
||||
Width="*" />
|
||||
</DataGrid.Columns>
|
||||
<DataGrid.RowStyle>
|
||||
<Style TargetType="DataGridRow"
|
||||
BasedOn="{StaticResource MahApps.Styles.DataGridRow}">
|
||||
<EventSetter Event="MouseDoubleClick"
|
||||
Handler="HandleItemDataGridRowMouseDoubleClick" />
|
||||
</Style>
|
||||
</DataGrid.RowStyle>
|
||||
</DataGrid>
|
||||
<Border Grid.Column="0"
|
||||
Grid.Row="1"
|
||||
BorderThickness="1,0,1,1"
|
||||
BorderBrush="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}">
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
|
||||
<controls:Link Name="AddItemButton"
|
||||
Margin="2"
|
||||
Click="HandleAddItemButtonClick"
|
||||
Text="{x:Static properties:Resources.AddItemLink}"
|
||||
ToolTip="{x:Static properties:Resources.AddItemToolTip}">
|
||||
</controls:Link>
|
||||
<controls:Link Name="EditItemButton"
|
||||
Margin="2"
|
||||
Click="HandleEditItemButtonClick"
|
||||
Text="{x:Static properties:Resources.EditItemLink}"
|
||||
ToolTip="{x:Static properties:Resources.EditItemToolTip}">
|
||||
</controls:Link>
|
||||
<controls:Link Name="DeleteItemButton"
|
||||
Margin="2"
|
||||
Click="HandleDeleteItemButtonClick"
|
||||
Text="{x:Static properties:Resources.DeleteItemLink}"
|
||||
ToolTip="{x:Static properties:Resources.DeleteItemToolTip}">
|
||||
</controls:Link>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</windows:CategoryPanelBase>
|
||||
112
Template/SettingsWindow/ItemsSettingsPanel.xaml.cs
Normal file
112
Template/SettingsWindow/ItemsSettingsPanel.xaml.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Template.SettingsWindow;
|
||||
|
||||
public partial class ItemsSettingsPanel
|
||||
{
|
||||
private CollectionViewSource _collectionViewSource;
|
||||
|
||||
public ItemsSettingsPanel()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public override string CategoryName => Properties.Resources.optionCategoryItems;
|
||||
|
||||
public override void LoadPanel(Window parentWindow)
|
||||
{
|
||||
base.LoadPanel(parentWindow);
|
||||
|
||||
if (_collectionViewSource == null)
|
||||
{
|
||||
_collectionViewSource = new CollectionViewSource { Source = Data.ItemEntries };
|
||||
|
||||
ItemDataGrid.ItemsSource = _collectionViewSource.View;
|
||||
}
|
||||
|
||||
_collectionViewSource.View.Refresh();
|
||||
|
||||
if (ItemDataGrid.Items.Count > 0)
|
||||
ItemDataGrid.SelectedIndex = 0;
|
||||
|
||||
SetItemButtonStates();
|
||||
}
|
||||
|
||||
private void HandleItemDataGridSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
SetItemButtonStates();
|
||||
}
|
||||
|
||||
private void SetItemButtonStates()
|
||||
{
|
||||
AddItemButton.IsEnabled = true;
|
||||
EditItemButton.IsEnabled = ItemDataGrid.SelectedItems.Count == 1;
|
||||
DeleteItemButton.IsEnabled = ItemDataGrid.SelectedItems.Count > 0;
|
||||
}
|
||||
|
||||
private void HandleAddItemButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AddItem();
|
||||
}
|
||||
|
||||
private void HandleEditItemButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
EditSelectedItem();
|
||||
}
|
||||
|
||||
private void HandleDeleteItemButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DeleteSelectedItems();
|
||||
}
|
||||
|
||||
private void HandleItemDataGridRowMouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
EditSelectedItem();
|
||||
}
|
||||
|
||||
private void AddItem()
|
||||
{
|
||||
var itemEntry = new ItemEntry { };
|
||||
|
||||
var itemWindow = new ItemWindow();
|
||||
|
||||
var result = itemWindow.Display(itemEntry, Window.GetWindow(this));
|
||||
|
||||
if (!result.HasValue || !result.Value)
|
||||
return;
|
||||
|
||||
ItemDataGrid.SelectedItem = itemEntry;
|
||||
|
||||
SetItemButtonStates();
|
||||
}
|
||||
|
||||
private void EditSelectedItem()
|
||||
{
|
||||
if (ItemDataGrid.SelectedItem == null)
|
||||
return;
|
||||
|
||||
var itemEntry = (ItemEntry)ItemDataGrid.SelectedItem;
|
||||
|
||||
var itemWindow = new ItemWindow();
|
||||
|
||||
itemWindow.Display(itemEntry, Window.GetWindow(this));
|
||||
}
|
||||
|
||||
private void DeleteSelectedItems()
|
||||
{
|
||||
if (MessageBox.Show(ParentWindow!, Properties.Resources.ConfirmDeleteItemss, Properties.Resources.ConfirmDeleteTitle, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.No)
|
||||
return;
|
||||
|
||||
var selectedItems = new ItemEntry[ItemDataGrid.SelectedItems.Count];
|
||||
|
||||
ItemDataGrid.SelectedItems.CopyTo(selectedItems, 0);
|
||||
|
||||
foreach (var itemEntry in selectedItems)
|
||||
Data.ItemEntries.Remove(itemEntry);
|
||||
|
||||
SetItemButtonStates();
|
||||
}
|
||||
}
|
||||
22
Template/SettingsWindow/UpdateSettingsPanel.xaml
Normal file
22
Template/SettingsWindow/UpdateSettingsPanel.xaml
Normal file
@@ -0,0 +1,22 @@
|
||||
<windows:CategoryPanelBase x:Class="Template.SettingsWindow.UpdateSettingsPanel"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:properties="clr-namespace:Template.Properties"
|
||||
xmlns:windows="clr-namespace:ChrisKaczor.Wpf.Windows;assembly=ChrisKaczor.Wpf.Windows.CategoryWindow"
|
||||
xmlns:template="clr-namespace:Template"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="150"
|
||||
d:DesignWidth="250">
|
||||
<StackPanel windows:Spacing.Vertical="10">
|
||||
<CheckBox Content="{x:Static properties:Resources.checkVersionOnStartupCheckBox}"
|
||||
Name="CheckVersionOnStartupCheckBox"
|
||||
IsChecked="{Binding Source={x:Static properties:Settings.Default}, Path=CheckVersionAtStartup}"
|
||||
Click="OnSaveSettings" />
|
||||
<Button Content="{x:Static properties:Resources.checkVersionNowButton}"
|
||||
IsEnabled="{Binding Source={x:Static template:UpdateCheck.IsInstalled}}"
|
||||
HorizontalAlignment="Left"
|
||||
Click="HandleCheckVersionNowButtonClick" />
|
||||
</StackPanel>
|
||||
</windows:CategoryPanelBase>
|
||||
38
Template/SettingsWindow/UpdateSettingsPanel.xaml.cs
Normal file
38
Template/SettingsWindow/UpdateSettingsPanel.xaml.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Template.Properties;
|
||||
|
||||
namespace Template.SettingsWindow;
|
||||
|
||||
public partial class UpdateSettingsPanel
|
||||
{
|
||||
public UpdateSettingsPanel()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public override string CategoryName => Properties.Resources.optionCategoryUpdate;
|
||||
|
||||
private async void HandleCheckVersionNowButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var cursor = Cursor;
|
||||
|
||||
Cursor = Cursors.Wait;
|
||||
|
||||
await UpdateCheck.DisplayUpdateInformation(true);
|
||||
|
||||
Cursor = cursor;
|
||||
}
|
||||
|
||||
private void OnSaveSettings(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
private void SaveSettings()
|
||||
{
|
||||
if (!HasLoaded) return;
|
||||
|
||||
Settings.Default.Save();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user