mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 18:28:00 +00:00
- New Game Log Verbosity setting.
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -14914,6 +14914,7 @@ src/main/java/forge/gui/package-info.java svneol=native#text/plain
|
||||
src/main/java/forge/gui/toolbox/CardFaceSymbols.java svneol=native#text/plain
|
||||
src/main/java/forge/gui/toolbox/FButton.java -text
|
||||
src/main/java/forge/gui/toolbox/FCheckBox.java -text
|
||||
src/main/java/forge/gui/toolbox/FComboBoxPanel.java -text
|
||||
src/main/java/forge/gui/toolbox/FLabel.java -text
|
||||
src/main/java/forge/gui/toolbox/FList.java -text
|
||||
src/main/java/forge/gui/toolbox/FOverlay.java -text
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.Observable;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import forge.game.event.IGameEventVisitor;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
|
||||
|
||||
/**
|
||||
@@ -103,6 +104,11 @@ public class GameLog extends Observable {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public GameLogEntryType getGameLogEntryTypeSetting() {
|
||||
String logEntryType = Singletons.getModel().getPreferences().getPref(FPref.DEV_LOG_ENTRY_TYPE);
|
||||
return GameLogEntryType.valueOf(logEntryType);
|
||||
}
|
||||
|
||||
public IGameEventVisitor<?> getEventVisitor() {
|
||||
return formatter;
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import forge.Command;
|
||||
import forge.Constant.Preferences;
|
||||
import forge.GameLogEntryType;
|
||||
import forge.Singletons;
|
||||
import forge.control.FControl.Screens;
|
||||
import forge.control.RestartUtil;
|
||||
@@ -73,6 +74,15 @@ public enum CSubmenuPreferences implements ICDoc {
|
||||
prefs.save();
|
||||
}
|
||||
});
|
||||
|
||||
view.getCboLogEntryType().addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(final ItemEvent e) {
|
||||
GameLogEntryType selectedType = (GameLogEntryType) view.getCboLogEntryType().getSelectedItem();
|
||||
prefs.setPref(FPref.DEV_LOG_ENTRY_TYPE, selectedType.toString());
|
||||
prefs.save();
|
||||
}
|
||||
});
|
||||
|
||||
lstControls.clear(); // just in case
|
||||
lstControls.add(Pair.of(view.getCbCompactMainMenu(), FPref.UI_COMPACT_MAIN_MENU));
|
||||
@@ -145,6 +155,7 @@ public enum CSubmenuPreferences implements ICDoc {
|
||||
updateAIProfiles();
|
||||
|
||||
view.getCbDevMode().setSelected(prefs.getPrefBoolean(FPref.DEV_MODE_ENABLED));
|
||||
view.getCboLogEntryType().setSelectedItem(GameLogEntryType.valueOf(prefs.getPref(FPref.DEV_LOG_ENTRY_TYPE)));
|
||||
|
||||
for(Pair<JCheckBox, FPref> kv: lstControls) {
|
||||
kv.getKey().setSelected(prefs.getPrefBoolean(kv.getValue()));
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
@@ -26,6 +27,7 @@ import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.GameLogEntryType;
|
||||
import forge.Singletons;
|
||||
import forge.control.KeyboardShortcuts;
|
||||
import forge.control.KeyboardShortcuts.Shortcut;
|
||||
@@ -36,6 +38,7 @@ import forge.gui.home.EMenuGroup;
|
||||
import forge.gui.home.IVSubmenu;
|
||||
import forge.gui.home.VHomeUI;
|
||||
import forge.gui.toolbox.FCheckBox;
|
||||
import forge.gui.toolbox.FComboBoxPanel;
|
||||
import forge.gui.toolbox.FLabel;
|
||||
import forge.gui.toolbox.FList;
|
||||
import forge.gui.toolbox.FScrollPane;
|
||||
@@ -92,6 +95,8 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
private final JCheckBox cbStackLand = new OptionsCheckBox("Stack AI Land");
|
||||
private final JCheckBox cbManaBurn = new OptionsCheckBox("Mana Burn");
|
||||
private final JCheckBox cbDevMode = new OptionsCheckBox("Developer Mode");
|
||||
private final FComboBoxPanel<GameLogEntryType> cbpLogEntryType =
|
||||
new FComboBoxPanel<GameLogEntryType>(GameLogEntryType.values(), "Game Log Verbosity:");
|
||||
private final JCheckBox cbEnforceDeckLegality = new OptionsCheckBox("Deck Conformance");
|
||||
private final JCheckBox cbCloneImgSource = new OptionsCheckBox("Clones use original card art");
|
||||
private final JCheckBox cbOverlayCardName = new OptionsCheckBox("Card Name");
|
||||
@@ -153,6 +158,9 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
pnlPrefs.add(cbDevMode, regularConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Enables menu with functions for testing during development."), regularConstraints);
|
||||
|
||||
pnlPrefs.add(cbpLogEntryType, "w 80%!, gap 10% 0 0 10px, span 2 1");
|
||||
pnlPrefs.add(new NoteLabel("Changes how much information is displayed in the game log. Sorted by least to most verbose."), regularConstraints);
|
||||
|
||||
pnlPrefs.add(cbEnforceDeckLegality, regularConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Enforces deck legality relevant to each environment (minimum deck sizes, max card count etc)"), regularConstraints);
|
||||
|
||||
@@ -227,7 +235,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
|
||||
scrContent.setBorder(null);
|
||||
}
|
||||
|
||||
|
||||
public void reloadShortcuts() {
|
||||
for (Map.Entry<FPref, KeyboardShortcutField> e : shortcutFields.entrySet()) {
|
||||
e.getValue().reload(e.getKey());
|
||||
@@ -492,6 +500,11 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
public JCheckBox getCbDevMode() {
|
||||
return cbDevMode;
|
||||
}
|
||||
|
||||
/** @return {@link javax.swing.JComboBox} */
|
||||
public JComboBox<GameLogEntryType> getCboLogEntryType() {
|
||||
return cbpLogEntryType.getJComboBox();
|
||||
}
|
||||
|
||||
/** @return {@link javax.swing.JCheckBox} */
|
||||
public JCheckBox getCbEnforceDeckLegality() {
|
||||
|
||||
@@ -1,146 +1,143 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Nate
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.gui.match.views;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import forge.GameLog;
|
||||
import forge.GameLogEntry;
|
||||
import forge.GameLogEntryType;
|
||||
import forge.gui.framework.DragCell;
|
||||
import forge.gui.framework.DragTab;
|
||||
import forge.gui.framework.EDocID;
|
||||
import forge.gui.framework.IVDoc;
|
||||
import forge.gui.match.controllers.CLog;
|
||||
import forge.gui.toolbox.FSkin;
|
||||
|
||||
/**
|
||||
* Assembles Swing components of game log report.
|
||||
*
|
||||
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
|
||||
*/
|
||||
public enum VLog implements IVDoc<CLog> {
|
||||
/** */
|
||||
SINGLETON_INSTANCE;
|
||||
|
||||
// Fields used with interface IVDoc
|
||||
private DragCell parentCell;
|
||||
private final DragTab tab = new DragTab("Log");
|
||||
|
||||
// Other fields
|
||||
private final JPanel pnl = new JPanel(new MigLayout("insets 0, gap 0, wrap"));
|
||||
private final JScrollPane scroller = new JScrollPane(pnl);
|
||||
|
||||
//========== Constructor
|
||||
private VLog() {
|
||||
scroller.setOpaque(false);
|
||||
scroller.setBorder(null);
|
||||
scroller.getViewport().setOpaque(false);
|
||||
|
||||
pnl.setOpaque(false);
|
||||
}
|
||||
|
||||
//========== Overridden methods
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#populate()
|
||||
*/
|
||||
@Override
|
||||
public void populate() {
|
||||
// (Panel uses observers to update, no permanent components here.)
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#setParentCell()
|
||||
*/
|
||||
@Override
|
||||
public void setParentCell(final DragCell cell0) {
|
||||
this.parentCell = cell0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#getParentCell()
|
||||
*/
|
||||
@Override
|
||||
public DragCell getParentCell() {
|
||||
return this.parentCell;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#getDocumentID()
|
||||
*/
|
||||
@Override
|
||||
public EDocID getDocumentID() {
|
||||
return EDocID.REPORT_LOG;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#getTabLabel()
|
||||
*/
|
||||
@Override
|
||||
public DragTab getTabLabel() {
|
||||
return tab;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#getLayoutControl()
|
||||
*/
|
||||
@Override
|
||||
public CLog getLayoutControl() {
|
||||
return CLog.SINGLETON_INSTANCE;
|
||||
}
|
||||
|
||||
//========== Observer update methods
|
||||
/**
|
||||
* @param model */
|
||||
public void updateConsole(GameLog model) {
|
||||
// No need to update this unless it's showing
|
||||
if (!parentCell.getSelected().equals(this)) { return; }
|
||||
|
||||
// TODO - some option to make this configurable is probably desirable
|
||||
// By default, grab everything log level 3 or less.
|
||||
final List<GameLogEntry> data = model.getLogEntries(GameLogEntryType.DAMAGE);
|
||||
final int size = data.size();
|
||||
|
||||
pnl.removeAll();
|
||||
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
JTextArea tar = new JTextArea(data.get(i).message);
|
||||
|
||||
if (i % 2 == 1) { tar.setOpaque(false); }
|
||||
else { tar.setBackground(FSkin.getColor(FSkin.Colors.CLR_ZEBRA)); }
|
||||
tar.setBorder(new EmptyBorder(2, 2, 2, 2));
|
||||
tar.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
||||
|
||||
tar.setFocusable(false);
|
||||
tar.setEditable(false);
|
||||
tar.setLineWrap(true);
|
||||
tar.setWrapStyleWord(true);
|
||||
|
||||
pnl.add(tar, "w 98%!, gap 1% 0 0 0");
|
||||
}
|
||||
|
||||
parentCell.getBody().setLayout(new MigLayout("insets 0, gap 0, wrap"));
|
||||
parentCell.getBody().add(scroller, "w 98%!, pushy, growy, gap 1% 0 5px 5px");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Nate
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.gui.match.views;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import forge.GameLog;
|
||||
import forge.GameLogEntry;
|
||||
import forge.gui.framework.DragCell;
|
||||
import forge.gui.framework.DragTab;
|
||||
import forge.gui.framework.EDocID;
|
||||
import forge.gui.framework.IVDoc;
|
||||
import forge.gui.match.controllers.CLog;
|
||||
import forge.gui.toolbox.FSkin;
|
||||
|
||||
/**
|
||||
* Assembles Swing components of game log report.
|
||||
*
|
||||
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
|
||||
*/
|
||||
public enum VLog implements IVDoc<CLog> {
|
||||
/** */
|
||||
SINGLETON_INSTANCE;
|
||||
|
||||
// Fields used with interface IVDoc
|
||||
private DragCell parentCell;
|
||||
private final DragTab tab = new DragTab("Log");
|
||||
|
||||
// Other fields
|
||||
private final JPanel pnl = new JPanel(new MigLayout("insets 0, gap 0, wrap"));
|
||||
private final JScrollPane scroller = new JScrollPane(pnl);
|
||||
|
||||
//========== Constructor
|
||||
private VLog() {
|
||||
scroller.setOpaque(false);
|
||||
scroller.setBorder(null);
|
||||
scroller.getViewport().setOpaque(false);
|
||||
|
||||
pnl.setOpaque(false);
|
||||
}
|
||||
|
||||
//========== Overridden methods
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#populate()
|
||||
*/
|
||||
@Override
|
||||
public void populate() {
|
||||
// (Panel uses observers to update, no permanent components here.)
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#setParentCell()
|
||||
*/
|
||||
@Override
|
||||
public void setParentCell(final DragCell cell0) {
|
||||
this.parentCell = cell0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#getParentCell()
|
||||
*/
|
||||
@Override
|
||||
public DragCell getParentCell() {
|
||||
return this.parentCell;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#getDocumentID()
|
||||
*/
|
||||
@Override
|
||||
public EDocID getDocumentID() {
|
||||
return EDocID.REPORT_LOG;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#getTabLabel()
|
||||
*/
|
||||
@Override
|
||||
public DragTab getTabLabel() {
|
||||
return tab;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.IVDoc#getLayoutControl()
|
||||
*/
|
||||
@Override
|
||||
public CLog getLayoutControl() {
|
||||
return CLog.SINGLETON_INSTANCE;
|
||||
}
|
||||
|
||||
//========== Observer update methods
|
||||
/**
|
||||
* @param model */
|
||||
public void updateConsole(GameLog model) {
|
||||
// No need to update this unless it's showing
|
||||
if (!parentCell.getSelected().equals(this)) { return; }
|
||||
|
||||
final List<GameLogEntry> data = model.getLogEntries(model.getGameLogEntryTypeSetting());
|
||||
final int size = data.size();
|
||||
|
||||
pnl.removeAll();
|
||||
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
JTextArea tar = new JTextArea(data.get(i).message);
|
||||
|
||||
if (i % 2 == 1) { tar.setOpaque(false); }
|
||||
else { tar.setBackground(FSkin.getColor(FSkin.Colors.CLR_ZEBRA)); }
|
||||
tar.setBorder(new EmptyBorder(2, 2, 2, 2));
|
||||
tar.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
||||
|
||||
tar.setFocusable(false);
|
||||
tar.setEditable(false);
|
||||
tar.setLineWrap(true);
|
||||
tar.setWrapStyleWord(true);
|
||||
|
||||
pnl.add(tar, "w 98%!, gap 1% 0 0 0");
|
||||
}
|
||||
|
||||
parentCell.getBody().setLayout(new MigLayout("insets 0, gap 0, wrap"));
|
||||
parentCell.getBody().add(scroller, "w 98%!, pushy, growy, gap 1% 0 5px 5px");
|
||||
}
|
||||
}
|
||||
|
||||
85
src/main/java/forge/gui/toolbox/FComboBoxPanel.java
Normal file
85
src/main/java/forge/gui/toolbox/FComboBoxPanel.java
Normal file
@@ -0,0 +1,85 @@
|
||||
package forge.gui.toolbox;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.FlowLayout;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class FComboBoxPanel<E> extends JPanel {
|
||||
|
||||
private String comboBoxCaption = "";
|
||||
private final JComboBox<E> comboBox;
|
||||
|
||||
public FComboBoxPanel(E[] comboBoxItems, String comboBoxCaption) {
|
||||
super();
|
||||
this.comboBox = new JComboBox<E>(comboBoxItems);
|
||||
this.comboBoxCaption = comboBoxCaption;
|
||||
applyLayoutAndSkin();
|
||||
}
|
||||
|
||||
public final JComboBox<E> getJComboBox() {
|
||||
return this.comboBox;
|
||||
}
|
||||
|
||||
private void applyLayoutAndSkin() {
|
||||
|
||||
FlowLayout panelLayout = new FlowLayout(FlowLayout.LEFT);
|
||||
panelLayout.setVgap(0);
|
||||
this.setLayout(panelLayout);
|
||||
this.setOpaque(false);
|
||||
|
||||
if (this.comboBoxCaption != "") {
|
||||
JLabel comboLabel;
|
||||
comboLabel = new JLabel(this.comboBoxCaption);
|
||||
comboLabel.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
||||
comboLabel.setFont(FSkin.getBoldFont(12));
|
||||
this.add(comboLabel);
|
||||
}
|
||||
|
||||
this.comboBox.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
|
||||
this.comboBox.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
||||
this.comboBox.setFont(FSkin.getFont(12));
|
||||
this.comboBox.setEditable(false);
|
||||
this.comboBox.setFocusable(true);
|
||||
this.comboBox.setOpaque(true);
|
||||
this.comboBox.setRenderer(new ComplexCellRenderer<E>());
|
||||
this.add(this.comboBox);
|
||||
|
||||
}
|
||||
|
||||
private class ComplexCellRenderer<E1> implements ListCellRenderer<E1> {
|
||||
|
||||
private DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.swing.ListCellRenderer#getListCellRendererComponent(javax.swing.JList, java.lang.Object, int, boolean, boolean)
|
||||
*/
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<? extends E1> lst0, E1 val0, int i0,
|
||||
boolean isSelected, boolean cellHasFocus) {
|
||||
|
||||
JLabel lblItem = (JLabel) defaultRenderer.getListCellRendererComponent(
|
||||
lst0, val0, i0, isSelected, cellHasFocus);
|
||||
|
||||
lblItem.setBorder(new EmptyBorder(4, 3, 4, 3));
|
||||
lblItem.setBackground(FSkin.getColor(hasFocus() ? FSkin.Colors.CLR_ACTIVE : FSkin.Colors.CLR_INACTIVE));
|
||||
lblItem.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
||||
lblItem.setFont(FSkin.getFont(12));
|
||||
lblItem.setOpaque(isSelected);
|
||||
return lblItem;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
|
||||
import forge.Constant;
|
||||
import forge.Constant.Preferences;
|
||||
import forge.GameLogEntryType;
|
||||
import forge.game.ai.AiProfileUtil;
|
||||
import forge.gui.home.EMenuItem;
|
||||
import forge.gui.match.VMatchUI;
|
||||
@@ -74,6 +75,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
|
||||
DEV_MODE_ENABLED ("false"),
|
||||
DEV_MILLING_LOSS ("true"),
|
||||
DEV_UNLIMITED_LAND ("false"),
|
||||
DEV_LOG_ENTRY_TYPE (GameLogEntryType.DAMAGE.toString()),
|
||||
|
||||
DECKGEN_SINGLETONS ("false"),
|
||||
DECKGEN_ARTIFACTS ("false"),
|
||||
|
||||
Reference in New Issue
Block a user