mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1055032 part 5 - Rename InsertElementTxn to InsertNodeTxn and clean up; r=ehsan
--HG-- rename : editor/libeditor/InsertElementTxn.cpp => editor/libeditor/InsertNodeTxn.cpp rename : editor/libeditor/InsertElementTxn.h => editor/libeditor/InsertNodeTxn.h
This commit is contained in:
parent
40c68fb20c
commit
e49b3bdc72
@ -1,112 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <stdio.h> // for printf
|
||||
|
||||
#include "InsertElementTxn.h"
|
||||
#include "nsAString.h"
|
||||
#include "nsDebug.h" // for NS_ENSURE_TRUE, etc
|
||||
#include "nsEditor.h" // for nsEditor
|
||||
#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc
|
||||
#include "nsIContent.h" // for nsIContent
|
||||
#include "nsINode.h" // for nsINode
|
||||
#include "nsISelection.h" // for nsISelection
|
||||
#include "nsMemory.h" // for nsMemory
|
||||
#include "nsReadableUtils.h" // for ToNewCString
|
||||
#include "nsString.h" // for nsString
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
InsertElementTxn::InsertElementTxn()
|
||||
: EditTxn()
|
||||
{
|
||||
}
|
||||
|
||||
InsertElementTxn::~InsertElementTxn()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertElementTxn, EditTxn,
|
||||
mNode,
|
||||
mParent)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(InsertElementTxn, EditTxn)
|
||||
NS_IMPL_RELEASE_INHERITED(InsertElementTxn, EditTxn)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertElementTxn)
|
||||
NS_INTERFACE_MAP_END_INHERITING(EditTxn)
|
||||
|
||||
NS_IMETHODIMP InsertElementTxn::Init(nsIDOMNode *aNode,
|
||||
nsIDOMNode *aParent,
|
||||
int32_t aOffset,
|
||||
nsIEditor *aEditor)
|
||||
{
|
||||
NS_ASSERTION(aNode && aParent && aEditor, "bad arg");
|
||||
NS_ENSURE_TRUE(aNode && aParent && aEditor, NS_ERROR_NULL_POINTER);
|
||||
|
||||
mNode = do_QueryInterface(aNode);
|
||||
mParent = do_QueryInterface(aParent);
|
||||
mOffset = aOffset;
|
||||
mEditor = aEditor;
|
||||
NS_ENSURE_TRUE(mNode && mParent && mEditor, NS_ERROR_INVALID_ARG);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP InsertElementTxn::DoTransaction(void)
|
||||
{
|
||||
NS_ENSURE_TRUE(mNode && mParent, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsCOMPtr<nsINode> parent = do_QueryInterface(mParent);
|
||||
NS_ENSURE_STATE(parent);
|
||||
|
||||
uint32_t count = parent->GetChildCount();
|
||||
if (mOffset > int32_t(count) || mOffset == -1) {
|
||||
// -1 is sentinel value meaning "append at end"
|
||||
mOffset = count;
|
||||
}
|
||||
|
||||
// note, it's ok for refContent to be null. that means append
|
||||
nsCOMPtr<nsIContent> refContent = parent->GetChildAt(mOffset);
|
||||
nsCOMPtr<nsIDOMNode> refNode = refContent ? refContent->AsDOMNode() : nullptr;
|
||||
|
||||
mEditor->MarkNodeDirty(mNode);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
nsresult result = mParent->InsertBefore(mNode, refNode, getter_AddRefs(resultNode));
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
NS_ENSURE_TRUE(resultNode, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// only set selection to insertion point if editor gives permission
|
||||
bool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection)
|
||||
{
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
// place the selection just after the inserted element
|
||||
selection->Collapse(mParent, mOffset+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing - dom range gravity will adjust selection
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP InsertElementTxn::UndoTransaction(void)
|
||||
{
|
||||
NS_ENSURE_TRUE(mNode && mParent, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
return mParent->RemoveChild(mNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP InsertElementTxn::GetTxnDescription(nsAString& aString)
|
||||
{
|
||||
aString.AssignLiteral("InsertElementTxn");
|
||||
return NS_OK;
|
||||
}
|
93
editor/libeditor/InsertNodeTxn.cpp
Normal file
93
editor/libeditor/InsertNodeTxn.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <stdio.h> // for printf
|
||||
|
||||
#include "mozilla/dom/Selection.h" // for Selection
|
||||
|
||||
#include "InsertNodeTxn.h"
|
||||
#include "nsAString.h"
|
||||
#include "nsDebug.h" // for NS_ENSURE_TRUE, etc
|
||||
#include "nsEditor.h" // for nsEditor
|
||||
#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc
|
||||
#include "nsIContent.h" // for nsIContent
|
||||
#include "nsMemory.h" // for nsMemory
|
||||
#include "nsReadableUtils.h" // for ToNewCString
|
||||
#include "nsString.h" // for nsString
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
InsertNodeTxn::InsertNodeTxn(nsIContent& aNode, nsINode& aParent,
|
||||
int32_t aOffset, nsEditor& aEditor)
|
||||
: EditTxn()
|
||||
, mNode(&aNode)
|
||||
, mParent(&aParent)
|
||||
, mOffset(aOffset)
|
||||
, mEditor(aEditor)
|
||||
{
|
||||
}
|
||||
|
||||
InsertNodeTxn::~InsertNodeTxn()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertNodeTxn, EditTxn,
|
||||
mNode,
|
||||
mParent)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(InsertNodeTxn, EditTxn)
|
||||
NS_IMPL_RELEASE_INHERITED(InsertNodeTxn, EditTxn)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertNodeTxn)
|
||||
NS_INTERFACE_MAP_END_INHERITING(EditTxn)
|
||||
|
||||
NS_IMETHODIMP
|
||||
InsertNodeTxn::DoTransaction()
|
||||
{
|
||||
MOZ_ASSERT(mNode && mParent);
|
||||
|
||||
uint32_t count = mParent->GetChildCount();
|
||||
if (mOffset > static_cast<int32_t>(count) || mOffset == -1) {
|
||||
// -1 is sentinel value meaning "append at end"
|
||||
mOffset = count;
|
||||
}
|
||||
|
||||
// Note, it's ok for ref to be null. That means append.
|
||||
nsCOMPtr<nsIContent> ref = mParent->GetChildAt(mOffset);
|
||||
|
||||
mEditor.MarkNodeDirty(GetAsDOMNode(mNode));
|
||||
|
||||
ErrorResult rv;
|
||||
mParent->InsertBefore(*mNode, ref, rv);
|
||||
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
|
||||
|
||||
// Only set selection to insertion point if editor gives permission
|
||||
if (mEditor.GetShouldTxnSetSelection()) {
|
||||
nsRefPtr<Selection> selection = mEditor.GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
// Place the selection just after the inserted element
|
||||
selection->Collapse(mParent, mOffset + 1);
|
||||
} else {
|
||||
// Do nothing - DOM Range gravity will adjust selection
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InsertNodeTxn::UndoTransaction()
|
||||
{
|
||||
MOZ_ASSERT(mNode && mParent);
|
||||
|
||||
ErrorResult rv;
|
||||
mParent->RemoveChild(*mNode, rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InsertNodeTxn::GetTxnDescription(nsAString& aString)
|
||||
{
|
||||
aString.AssignLiteral("InsertNodeTxn");
|
||||
return NS_OK;
|
||||
}
|
@ -3,22 +3,24 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef InsertElementTxn_h__
|
||||
#define InsertElementTxn_h__
|
||||
#ifndef InsertNodeTxn_h__
|
||||
#define InsertNodeTxn_h__
|
||||
|
||||
#include "EditTxn.h" // for EditTxn, NS_DECL_EDITTXN
|
||||
#include "nsCOMPtr.h" // for nsCOMPtr
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIDOMNode.h" // for nsIDOMNode
|
||||
#include "nsIContent.h" // for nsIContent
|
||||
#include "nsISupportsImpl.h" // for NS_DECL_ISUPPORTS_INHERITED
|
||||
#include "nscore.h" // for NS_IMETHOD
|
||||
|
||||
class nsIEditor;
|
||||
class nsEditor;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/**
|
||||
* A transaction that inserts a single element
|
||||
*/
|
||||
class InsertElementTxn : public EditTxn
|
||||
class InsertNodeTxn : public EditTxn
|
||||
{
|
||||
public:
|
||||
/** initialize the transaction.
|
||||
@ -26,32 +28,31 @@ public:
|
||||
* @param aParent the node to insert into
|
||||
* @param aOffset the offset in aParent to insert aNode
|
||||
*/
|
||||
NS_IMETHOD Init(nsIDOMNode *aNode,
|
||||
nsIDOMNode *aParent,
|
||||
int32_t aOffset,
|
||||
nsIEditor *aEditor);
|
||||
|
||||
InsertElementTxn();
|
||||
InsertNodeTxn(nsIContent& aNode, nsINode& aParent, int32_t aOffset,
|
||||
nsEditor& aEditor);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(InsertElementTxn, EditTxn)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(InsertNodeTxn, EditTxn)
|
||||
|
||||
NS_DECL_EDITTXN
|
||||
|
||||
protected:
|
||||
virtual ~InsertElementTxn();
|
||||
virtual ~InsertNodeTxn();
|
||||
|
||||
/** the element to insert */
|
||||
nsCOMPtr<nsIDOMNode> mNode;
|
||||
nsCOMPtr<nsIContent> mNode;
|
||||
|
||||
/** the node into which the new node will be inserted */
|
||||
nsCOMPtr<nsIDOMNode> mParent;
|
||||
|
||||
/** the editor for this transaction */
|
||||
nsIEditor* mEditor;
|
||||
nsCOMPtr<nsINode> mParent;
|
||||
|
||||
/** the index in mParent for the new node */
|
||||
int32_t mOffset;
|
||||
|
||||
/** the editor for this transaction */
|
||||
nsEditor& mEditor;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -16,7 +16,7 @@ UNIFIED_SOURCES += [
|
||||
'EditAggregateTxn.cpp',
|
||||
'EditTxn.cpp',
|
||||
'IMETextTxn.cpp',
|
||||
'InsertElementTxn.cpp',
|
||||
'InsertNodeTxn.cpp',
|
||||
'InsertTextTxn.cpp',
|
||||
'JoinElementTxn.cpp',
|
||||
'nsEditor.cpp',
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "EditAggregateTxn.h" // for EditAggregateTxn
|
||||
#include "EditTxn.h" // for EditTxn
|
||||
#include "IMETextTxn.h" // for IMETextTxn
|
||||
#include "InsertElementTxn.h" // for InsertElementTxn
|
||||
#include "InsertNodeTxn.h" // for InsertNodeTxn
|
||||
#include "InsertTextTxn.h" // for InsertTextTxn
|
||||
#include "JoinElementTxn.h" // for JoinElementTxn
|
||||
#include "PlaceholderTxn.h" // for PlaceholderTxn
|
||||
@ -1386,38 +1386,38 @@ nsEditor::CreateNode(nsIAtom* aTag,
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::InsertNode(nsIContent* aContent, nsINode* aParent, int32_t aPosition)
|
||||
NS_IMETHODIMP
|
||||
nsEditor::InsertNode(nsIDOMNode* aNode, nsIDOMNode* aParent, int32_t aPosition)
|
||||
{
|
||||
MOZ_ASSERT(aContent && aParent);
|
||||
return InsertNode(GetAsDOMNode(aContent), GetAsDOMNode(aParent), aPosition);
|
||||
nsCOMPtr<nsIContent> node = do_QueryInterface(aNode);
|
||||
nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
|
||||
NS_ENSURE_TRUE(node && parent, NS_ERROR_NULL_POINTER);
|
||||
|
||||
return InsertNode(*node, *parent, aPosition);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsEditor::InsertNode(nsIDOMNode * aNode,
|
||||
nsIDOMNode * aParent,
|
||||
int32_t aPosition)
|
||||
nsresult
|
||||
nsEditor::InsertNode(nsIContent& aNode, nsINode& aParent, int32_t aPosition)
|
||||
{
|
||||
int32_t i;
|
||||
nsAutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
|
||||
|
||||
for (i = 0; i < mActionListeners.Count(); i++)
|
||||
mActionListeners[i]->WillInsertNode(aNode, aParent, aPosition);
|
||||
|
||||
nsRefPtr<InsertElementTxn> txn;
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
|
||||
nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
|
||||
nsresult result = CreateTxnForInsertElement(node->AsDOMNode(), parent->AsDOMNode(),
|
||||
aPosition, getter_AddRefs(txn));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = DoTransaction(txn);
|
||||
for (int32_t i = 0; i < mActionListeners.Count(); i++) {
|
||||
mActionListeners[i]->WillInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(),
|
||||
aPosition);
|
||||
}
|
||||
|
||||
mRangeUpdater.SelAdjInsertNode(aParent, aPosition);
|
||||
nsRefPtr<InsertNodeTxn> txn = CreateTxnForInsertNode(aNode, aParent,
|
||||
aPosition);
|
||||
nsresult res = DoTransaction(txn);
|
||||
|
||||
for (i = 0; i < mActionListeners.Count(); i++)
|
||||
mActionListeners[i]->DidInsertNode(aNode, aParent, aPosition, result);
|
||||
mRangeUpdater.SelAdjInsertNode(aParent.AsDOMNode(), aPosition);
|
||||
|
||||
return result;
|
||||
for (int32_t i = 0; i < mActionListeners.Count(); i++) {
|
||||
mActionListeners[i]->DidInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(),
|
||||
aPosition, res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -1582,13 +1582,13 @@ nsEditor::ReplaceContainer(Element* aOldContainer,
|
||||
res = DeleteNode(child);
|
||||
NS_ENSURE_SUCCESS(res, nullptr);
|
||||
|
||||
res = InsertNode(child, ret, -1);
|
||||
res = InsertNode(*child, *ret, -1);
|
||||
NS_ENSURE_SUCCESS(res, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// insert new container into tree
|
||||
res = InsertNode(ret, parent, offset);
|
||||
res = InsertNode(*ret, *parent, offset);
|
||||
NS_ENSURE_SUCCESS(res, nullptr);
|
||||
|
||||
// delete old container
|
||||
@ -1624,7 +1624,7 @@ nsEditor::RemoveContainer(nsIContent* aNode)
|
||||
nsresult rv = DeleteNode(child);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = InsertNode(child, parent, offset);
|
||||
rv = InsertNode(*child, *parent, offset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -1670,12 +1670,12 @@ nsEditor::InsertContainerAbove(nsIContent* aNode,
|
||||
|
||||
{
|
||||
nsAutoTxnsConserveSelection conserveSelection(this);
|
||||
res = InsertNode(aNode, newContent, 0);
|
||||
res = InsertNode(*aNode, *newContent, 0);
|
||||
NS_ENSURE_SUCCESS(res, nullptr);
|
||||
}
|
||||
|
||||
// Put new parent in doc
|
||||
res = InsertNode(newContent, parent, offset);
|
||||
res = InsertNode(*newContent, *parent, offset);
|
||||
NS_ENSURE_SUCCESS(res, nullptr);
|
||||
|
||||
return newContent.forget();
|
||||
@ -1720,7 +1720,7 @@ nsEditor::MoveNode(nsIContent* aNode, nsINode* aParent, int32_t aOffset)
|
||||
nsresult rv = DeleteNode(aNode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return InsertNode(aNode, aParent, aOffset);
|
||||
return InsertNode(*aNode, *aParent, aOffset);
|
||||
}
|
||||
|
||||
|
||||
@ -4304,22 +4304,14 @@ nsEditor::CreateTxnForCreateElement(nsIAtom& aTag,
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsEditor::CreateTxnForInsertElement(nsIDOMNode * aNode,
|
||||
nsIDOMNode * aParent,
|
||||
int32_t aPosition,
|
||||
InsertElementTxn ** aTxn)
|
||||
already_AddRefed<InsertNodeTxn>
|
||||
nsEditor::CreateTxnForInsertNode(nsIContent& aNode,
|
||||
nsINode& aParent,
|
||||
int32_t aPosition)
|
||||
{
|
||||
NS_ENSURE_TRUE(aNode && aParent, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsRefPtr<InsertElementTxn> txn = new InsertElementTxn();
|
||||
|
||||
nsresult rv = txn->Init(aNode, aParent, aPosition, this);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
txn.forget(aTxn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
nsRefPtr<InsertNodeTxn> txn = new InsertNodeTxn(aNode, aParent, aPosition,
|
||||
*this);
|
||||
return txn.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -32,7 +32,6 @@ class ChangeAttributeTxn;
|
||||
class DeleteNodeTxn;
|
||||
class EditAggregateTxn;
|
||||
class IMETextTxn;
|
||||
class InsertElementTxn;
|
||||
class InsertTextTxn;
|
||||
class JoinElementTxn;
|
||||
class RemoveStyleSheetTxn;
|
||||
@ -75,6 +74,7 @@ class DataTransfer;
|
||||
class DeleteTextTxn;
|
||||
class Element;
|
||||
class EventTarget;
|
||||
class InsertNodeTxn;
|
||||
class Selection;
|
||||
class Text;
|
||||
} // namespace dom
|
||||
@ -221,8 +221,7 @@ public:
|
||||
|
||||
/* helper routines for node/parent manipulations */
|
||||
nsresult DeleteNode(nsINode* aNode);
|
||||
nsresult InsertNode(nsIContent* aContent, nsINode* aParent,
|
||||
int32_t aPosition);
|
||||
nsresult InsertNode(nsIContent& aNode, nsINode& aParent, int32_t aPosition);
|
||||
enum ECloneAttributes { eDontCloneAttributes, eCloneAttributes };
|
||||
already_AddRefed<mozilla::dom::Element> ReplaceContainer(
|
||||
mozilla::dom::Element* aOldContainer,
|
||||
@ -285,10 +284,8 @@ protected:
|
||||
|
||||
/** create a transaction for inserting aNode as a child of aParent.
|
||||
*/
|
||||
NS_IMETHOD CreateTxnForInsertElement(nsIDOMNode * aNode,
|
||||
nsIDOMNode * aParent,
|
||||
int32_t aOffset,
|
||||
InsertElementTxn ** aTxn);
|
||||
already_AddRefed<mozilla::dom::InsertNodeTxn>
|
||||
CreateTxnForInsertNode(nsIContent& aNode, nsINode& aParent, int32_t aOffset);
|
||||
|
||||
/** create a transaction for removing aNode from its parent.
|
||||
*/
|
||||
|
@ -1254,7 +1254,7 @@ nsHTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
|
||||
|
||||
// Loop over the contents of the fragment and move into the document
|
||||
while (nsCOMPtr<nsIContent> child = docfrag->GetFirstChild()) {
|
||||
nsresult res = InsertNode(child, headNode, offsetOfNewNode++);
|
||||
nsresult res = InsertNode(*child, *headNode, offsetOfNewNode++);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user