mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 20:11:24 +08:00
Fixed xml-declaration tests.
This commit is contained in:
@ -56,7 +56,7 @@ allTests["CONNECTIVITY"] = require("./connectivity-tests");
|
|||||||
// allTests["PROXY-VIEW-CONTAINER"] = require("./ui/proxy-view-container/proxy-view-container-tests")
|
// allTests["PROXY-VIEW-CONTAINER"] = require("./ui/proxy-view-container/proxy-view-container-tests")
|
||||||
allTests["SCROLL-VIEW"] = require("./ui/scroll-view/scroll-view-tests");
|
allTests["SCROLL-VIEW"] = require("./ui/scroll-view/scroll-view-tests");
|
||||||
allTests["ACTION-BAR"] = require("./ui/action-bar/action-bar-tests");
|
allTests["ACTION-BAR"] = require("./ui/action-bar/action-bar-tests");
|
||||||
// allTests["XML-DECLARATION"] = require("./xml-declaration/xml-declaration-tests");
|
allTests["XML-DECLARATION"] = require("./xml-declaration/xml-declaration-tests");
|
||||||
allTests["DOCKLAYOUT"] = require("./ui/layouts/dock-layout-tests");
|
allTests["DOCKLAYOUT"] = require("./ui/layouts/dock-layout-tests");
|
||||||
allTests["WRAPLAYOUT"] = require("./ui/layouts/wrap-layout-tests");
|
allTests["WRAPLAYOUT"] = require("./ui/layouts/wrap-layout-tests");
|
||||||
allTests["ABSOLUTELAYOUT"] = require("./ui/layouts/absolute-layout-tests");
|
allTests["ABSOLUTELAYOUT"] = require("./ui/layouts/absolute-layout-tests");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {Template} from "ui/core/view"
|
import { Template } from "ui/core/view"
|
||||||
import {Property, PropertyMetadataSettings} from "ui/core/dependency-observable"
|
import { Property } from "ui/core/properties"
|
||||||
import * as proxy from "ui/core/proxy"
|
import * as proxy from "ui/core/proxy"
|
||||||
import { LayoutBase } from "ui/layouts/layout-base"
|
import { LayoutBase } from "ui/layouts/layout-base"
|
||||||
import { parse } from "ui/builder"
|
import { parse } from "ui/builder"
|
||||||
@ -9,27 +9,17 @@ export module knownTemplates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class TemplateView extends LayoutBase {
|
export class TemplateView extends LayoutBase {
|
||||||
public static templateProperty = new Property(
|
public template: string;
|
||||||
"template",
|
|
||||||
"TemplateView",
|
public static testEvent: string = "test";
|
||||||
new proxy.PropertyMetadata(
|
|
||||||
undefined,
|
|
||||||
PropertyMetadataSettings.AffectsLayout,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
public static testEvent: string = "test";
|
|
||||||
|
|
||||||
get template(): string | Template {
|
|
||||||
return this._getValue(TemplateView.templateProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
set template(value: string | Template) {
|
|
||||||
this._setValue(TemplateView.templateProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public parseTemplate() {
|
public parseTemplate() {
|
||||||
this.addChild(parse(this.template));
|
this.addChild(parse(this.template));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const templateProperty = new Property<TemplateView, string>({
|
||||||
|
name: "template",
|
||||||
|
affectsLayout: true
|
||||||
|
});
|
||||||
|
templateProperty.register(TemplateView);
|
||||||
|
@ -25,7 +25,7 @@ import * as platform from "platform";
|
|||||||
import * as gesturesModule from "ui/gestures";
|
import * as gesturesModule from "ui/gestures";
|
||||||
import * as segmentedBar from "ui/segmented-bar";
|
import * as segmentedBar from "ui/segmented-bar";
|
||||||
import { Source } from "utils/debug";
|
import { Source } from "utils/debug";
|
||||||
import { PercentLength } from "ui/core/view";
|
import { PercentLength, Length } from "ui/core/view";
|
||||||
|
|
||||||
export function test_load_IsDefined() {
|
export function test_load_IsDefined() {
|
||||||
TKUnit.assertTrue(types.isFunction(builder.load), "ui/builder should have load method!");
|
TKUnit.assertTrue(types.isFunction(builder.load), "ui/builder should have load method!");
|
||||||
@ -296,14 +296,15 @@ export function test_parse_ShouldSetGridAttachedProperties() {
|
|||||||
|
|
||||||
export function test_parse_ShouldSetCanvasAttachedProperties() {
|
export function test_parse_ShouldSetCanvasAttachedProperties() {
|
||||||
var p = <Page>builder.parse("<Page><AbsoluteLayout><Label left='1' top='2' right='3' bottom='4' /></AbsoluteLayout></Page>");
|
var p = <Page>builder.parse("<Page><AbsoluteLayout><Label left='1' top='2' right='3' bottom='4' /></AbsoluteLayout></Page>");
|
||||||
var grid = <gridLayoutModule.GridLayout>p.content;
|
var absLayout = <absoluteLayoutModule.AbsoluteLayout>p.content;
|
||||||
var child = grid.getChildAt(0);
|
var child = absLayout.getChildAt(0);
|
||||||
|
|
||||||
var left = absoluteLayoutModule.AbsoluteLayout.getLeft(child);
|
var left = absoluteLayoutModule.AbsoluteLayout.getLeft(child);
|
||||||
TKUnit.assertEqual(left, 1, "Expected result for canvas left: 1; Actual result: " + left + ";");
|
|
||||||
|
TKUnit.assert(Length.equals(left, Length.parse("1")), `Expected result for canvas left: 1; Actual result: ${(<any>left).value};`)
|
||||||
|
|
||||||
var top = absoluteLayoutModule.AbsoluteLayout.getTop(child);
|
var top = absoluteLayoutModule.AbsoluteLayout.getTop(child);
|
||||||
TKUnit.assertEqual(top, 2, "Expected result for canvas top: 2; Actual result: " + top + ";");
|
TKUnit.assert(Length.equals(top, Length.parse("2")), `Expected result for canvas top: 2; Actual result: ${(<any>top).value};`)
|
||||||
};
|
};
|
||||||
|
|
||||||
export function test_parse_ShouldParseNumberProperties() {
|
export function test_parse_ShouldParseNumberProperties() {
|
||||||
@ -445,13 +446,13 @@ export function test_parse_ShouldParseBindingsToGesturesWithOn() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function test_parse_ShouldParseSubProperties() {
|
export function test_parse_ShouldParseSubProperties() {
|
||||||
var p = <Page>builder.parse("<Page><Switch style.visibility='collapsed' checked='{{ myProp }}' /></Page>");
|
var p = <Page>builder.parse("<Page><Switch style.visibility='collapse' checked='{{ myProp }}' /></Page>");
|
||||||
var obj = new observable.Observable();
|
var obj = new observable.Observable();
|
||||||
obj.set("myProp", true);
|
obj.set("myProp", true);
|
||||||
p.bindingContext = obj;
|
p.bindingContext = obj;
|
||||||
var sw = <switchModule.Switch>p.content;
|
var sw = <switchModule.Switch>p.content;
|
||||||
|
|
||||||
TKUnit.assert(sw.visibility === "collapse", "Expected result: collapsed; Actual result: " + sw.visibility + "; type: " + typeof (sw.visibility));
|
TKUnit.assert(sw.visibility === "collapse", "Expected result: collapse; Actual result: " + sw.visibility + "; type: " + typeof (sw.visibility));
|
||||||
};
|
};
|
||||||
|
|
||||||
export function test_parse_ShouldParseBindingToSpecialProperty() {
|
export function test_parse_ShouldParseBindingToSpecialProperty() {
|
||||||
@ -539,10 +540,10 @@ export function test_parse_ShouldParseCustomComponentWithXml() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function test_parse_ShouldParseCustomComponentWithXml_WithAttributes() {
|
export function test_parse_ShouldParseCustomComponentWithXml_WithAttributes() {
|
||||||
var p = <Page>builder.parse('<Page xmlns:customControls="xml-declaration/mymodulewithxml"><customControls:MyControl visibility="collapsed" /></Page>');
|
var p = <Page>builder.parse('<Page xmlns:customControls="xml-declaration/mymodulewithxml"><customControls:MyControl visibility="collapse" /></Page>');
|
||||||
var panel = <stackLayoutModule.StackLayout>p.content;
|
var panel = <stackLayoutModule.StackLayout>p.content;
|
||||||
|
|
||||||
TKUnit.assertEqual(panel.visibility, "collapsed", "panel.visibility");
|
TKUnit.assertEqual(panel.visibility, "collapse", "panel.visibility");
|
||||||
};
|
};
|
||||||
|
|
||||||
export function test_parse_ShouldParseCustomComponentWithXml_WithCustomAttributes() {
|
export function test_parse_ShouldParseCustomComponentWithXml_WithCustomAttributes() {
|
||||||
@ -561,10 +562,10 @@ export function test_parse_ShouldParseCustomComponentWithXmlNoJS() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function test_parse_ShouldParseCustomComponentWithXmlNoJS_WithAttributes() {
|
export function test_parse_ShouldParseCustomComponentWithXmlNoJS_WithAttributes() {
|
||||||
var p = <Page>builder.parse('<Page xmlns:customControls="xml-declaration/mymodulewithxml"><customControls:my-control-no-js visibility="collapsed" /></Page>');
|
var p = <Page>builder.parse('<Page xmlns:customControls="xml-declaration/mymodulewithxml"><customControls:my-control-no-js visibility="collapse" /></Page>');
|
||||||
var panel = <stackLayoutModule.StackLayout>p.content;
|
var panel = <stackLayoutModule.StackLayout>p.content;
|
||||||
|
|
||||||
TKUnit.assertEqual(panel.visibility, "collapsed", "panel.visibility");
|
TKUnit.assertEqual(panel.visibility, "collapse", "panel.visibility");
|
||||||
};
|
};
|
||||||
|
|
||||||
export function test_parse_ShouldParseCustomComponentWithXmlNoJS_WithCustomAttributes() {
|
export function test_parse_ShouldParseCustomComponentWithXmlNoJS_WithCustomAttributes() {
|
||||||
@ -613,13 +614,23 @@ export function test_parse_ShouldParseNestedListViewInListViewTemplate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function test_parse_ShouldEvaluateEventBindingExpressionInListViewTemplate() {
|
export function test_parse_ShouldEvaluateEventBindingExpressionInListViewTemplate() {
|
||||||
var p = <Page>builder.parse('<Page xmlns="http://schemas.nativescript.org/tns.xsd"><ListView items="{{ items }}" itemLoading="{{ itemLoading }}"><ListView.itemTemplate><SegmentedBar items="{{ $parents[\'ListView\'].items }}" selectedIndexChanged="{{ $parents[\'ListView\'].changed }}" /></ListView.itemTemplate></ListView></Page>');
|
var p = <Page>builder.parse('<Page xmlns="http://schemas.nativescript.org/tns.xsd"><ListView items="{{ items }}" itemLoading="{{ itemLoading }}"><ListView.itemTemplate><SegmentedBar items="{{ $parents[\'ListView\'].segmentedBarItems }}" selectedIndexChanged="{{ $parents[\'ListView\'].changed }}" /></ListView.itemTemplate></ListView></Page>');
|
||||||
|
|
||||||
function testAction(views: Array<viewModule.View>) {
|
function testAction(views: Array<viewModule.View>) {
|
||||||
let ctrl: segmentedBar.SegmentedBar = null;
|
let ctrl: segmentedBar.SegmentedBar = null;
|
||||||
let changed;
|
let changed;
|
||||||
let obj = new observable.Observable();
|
let obj = new observable.Observable();
|
||||||
|
|
||||||
|
let firstItem = new segmentedBar.SegmentedBarItem();
|
||||||
|
firstItem.title = "One";
|
||||||
|
let secondItem = new segmentedBar.SegmentedBarItem();
|
||||||
|
secondItem.title = "Two";
|
||||||
|
let thirdItem = new segmentedBar.SegmentedBarItem();
|
||||||
|
thirdItem.title = "Tree";
|
||||||
|
let segmentedBarItems = [firstItem, secondItem, thirdItem];
|
||||||
|
|
||||||
obj.set("items", [1, 2, 3]);
|
obj.set("items", [1, 2, 3]);
|
||||||
|
obj.set("segmentedBarItems", segmentedBarItems);
|
||||||
obj.set("itemLoading", function (args: listViewModule.ItemEventData) {
|
obj.set("itemLoading", function (args: listViewModule.ItemEventData) {
|
||||||
ctrl = <segmentedBar.SegmentedBar>args.view
|
ctrl = <segmentedBar.SegmentedBar>args.view
|
||||||
});
|
});
|
||||||
|
@ -192,7 +192,7 @@ export class Binding {
|
|||||||
|
|
||||||
public loadedHandlerVisualTreeBinding(args) {
|
public loadedHandlerVisualTreeBinding(args) {
|
||||||
let target = args.object;
|
let target = args.object;
|
||||||
target.off(ViewBase.loadedEvent, this.loadedHandlerVisualTreeBinding, this);
|
target.off("loaded", this.loadedHandlerVisualTreeBinding, this);
|
||||||
if (!types.isNullOrUndefined(target.bindingContext)) {
|
if (!types.isNullOrUndefined(target.bindingContext)) {
|
||||||
this.bind(target.bindingContext);
|
this.bind(target.bindingContext);
|
||||||
}
|
}
|
||||||
@ -288,8 +288,8 @@ export class Binding {
|
|||||||
currentObject = parentView.bindingContext;
|
currentObject = parentView.bindingContext;
|
||||||
} else {
|
} else {
|
||||||
let targetInstance = this.target.get();
|
let targetInstance = this.target.get();
|
||||||
targetInstance.off(ViewBase.loadedEvent, this.loadedHandlerVisualTreeBinding, this);
|
targetInstance.off("loaded", this.loadedHandlerVisualTreeBinding, this);
|
||||||
targetInstance.on(ViewBase.loadedEvent, this.loadedHandlerVisualTreeBinding, this);
|
targetInstance.on("loaded", this.loadedHandlerVisualTreeBinding, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentObjectChanged = true;
|
currentObjectChanged = true;
|
||||||
|
@ -362,7 +362,6 @@ export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> imp
|
|||||||
if (currentValue !== newValue) {
|
if (currentValue !== newValue) {
|
||||||
|
|
||||||
if (this.hasListeners(eventName)) {
|
if (this.hasListeners(eventName)) {
|
||||||
console.log("Notify " + eventName);
|
|
||||||
this.notify({
|
this.notify({
|
||||||
eventName: eventName,
|
eventName: eventName,
|
||||||
propertyName: name,
|
propertyName: name,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { GestureEventData, SwipeGestureEventData, PanGestureEventData, RotationGestureEventData, PinchGestureEventData } from "ui/gestures";
|
import { GestureEventData, SwipeGestureEventData, PanGestureEventData, RotationGestureEventData, PinchGestureEventData } from "ui/gestures";
|
||||||
import { GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection, View, EventData } from "./gestures-common";
|
import { GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection, View, EventData } from "./gestures-common";
|
||||||
import { ios } from "utils/utils";
|
import { ios } from "utils/utils";
|
||||||
import getter = ios.getter;
|
import getter = ios.getter;
|
||||||
|
|
||||||
@ -92,8 +92,8 @@ export class GesturesObserver extends GesturesObserverBase {
|
|||||||
this._detach();
|
this._detach();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.target.on(View.loadedEvent, this._onTargetLoaded);
|
this.target.on("loaded", this._onTargetLoaded);
|
||||||
this.target.on(View.unloadedEvent, this._onTargetUnloaded);
|
this.target.on("unloaded", this._onTargetUnloaded);
|
||||||
|
|
||||||
if (this.target.isLoaded) {
|
if (this.target.isLoaded) {
|
||||||
this._attach(this.target, type);
|
this._attach(this.target, type);
|
||||||
@ -183,8 +183,8 @@ export class GesturesObserver extends GesturesObserverBase {
|
|||||||
this._detach();
|
this._detach();
|
||||||
|
|
||||||
if (this.target) {
|
if (this.target) {
|
||||||
this.target.off(View.loadedEvent, this._onTargetLoaded);
|
this.target.off("loaded", this._onTargetLoaded);
|
||||||
this.target.off(View.unloadedEvent, this._onTargetUnloaded);
|
this.target.off("unloaded", this._onTargetUnloaded);
|
||||||
|
|
||||||
this._onTargetLoaded = null;
|
this._onTargetLoaded = null;
|
||||||
this._onTargetUnloaded = null;
|
this._onTargetUnloaded = null;
|
||||||
|
@ -67,5 +67,3 @@ export class HtmlView extends HtmlViewBase {
|
|||||||
this._ios.attributedText = NSAttributedString.alloc().initWithDataOptionsDocumentAttributesError(nsData, <any>{ [NSDocumentTypeDocumentAttribute]: NSHTMLTextDocumentType }, null);
|
this._ios.attributedText = NSAttributedString.alloc().initWithDataOptionsDocumentAttributesError(nsData, <any>{ [NSDocumentTypeDocumentAttribute]: NSHTMLTextDocumentType }, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
htmlProperty.register(HtmlView);
|
|
@ -1,5 +1,5 @@
|
|||||||
declare module "ui/layouts/absolute-layout" {
|
declare module "ui/layouts/absolute-layout" {
|
||||||
import { LayoutBase, View, Property } from "ui/layouts/layout-base";
|
import { LayoutBase, View, Property, Length } from "ui/layouts/layout-base";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A layout that lets you specify exact locations (left/top coordinates) of its children.
|
* A layout that lets you specify exact locations (left/top coordinates) of its children.
|
||||||
@ -8,31 +8,31 @@
|
|||||||
/**
|
/**
|
||||||
* Gets the value of the Left property from a given View.
|
* Gets the value of the Left property from a given View.
|
||||||
*/
|
*/
|
||||||
static getLeft(view: View): number;
|
static getLeft(view: View): Length;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value of the Left property from a given View.
|
* Sets the value of the Left property from a given View.
|
||||||
*/
|
*/
|
||||||
static setLeft(view: View, value: number): void;
|
static setLeft(view: View, value: Length): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of the Top property from a given View.
|
* Gets the value of the Top property from a given View.
|
||||||
*/
|
*/
|
||||||
static getTop(view: View): number;
|
static getTop(view: View): Length;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value of the Top property from a given View.
|
* Sets the value of the Top property from a given View.
|
||||||
*/
|
*/
|
||||||
static setTop(view: View, value: number): void;
|
static setTop(view: View, value: Length): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the observable property backing the left property.
|
* Represents the observable property backing the left property.
|
||||||
*/
|
*/
|
||||||
export const leftProperty: Property<View, number>;
|
export const leftProperty: Property<View, Length>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the observable property backing the top property.
|
* Represents the observable property backing the top property.
|
||||||
*/
|
*/
|
||||||
export const topProperty: Property<View, number>;
|
export const topProperty: Property<View, Length>;
|
||||||
}
|
}
|
@ -46,6 +46,7 @@ export abstract class SegmentedBarBase extends View implements SegmentedBarDefin
|
|||||||
this.items = new Array<SegmentedBarItemBase>();
|
this.items = new Array<SegmentedBarItemBase>();
|
||||||
}
|
}
|
||||||
this.items.push(<SegmentedBarItemBase>value);
|
this.items.push(<SegmentedBarItemBase>value);
|
||||||
|
selectedIndexProperty.coerce(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,9 +259,9 @@ export class SegmentedBar extends SegmentedBarBase {
|
|||||||
if (newItems) {
|
if (newItems) {
|
||||||
newItems.forEach((item, i, arr) => this.insertTab(item, i));
|
newItems.forEach((item, i, arr) => this.insertTab(item, i));
|
||||||
|
|
||||||
if (this.selectedIndex < 0) {
|
// if (this.selectedIndex < 0) {
|
||||||
this.selectedIndex = tabHost.getCurrentTab();
|
// this.selectedIndex = tabHost.getCurrentTab();
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,9 +57,9 @@ export class SegmentedBar extends SegmentedBarBase {
|
|||||||
segmentedControl.insertSegmentWithTitleAtIndexAnimated(title, index, false);
|
segmentedControl.insertSegmentWithTitleAtIndexAnimated(title, index, false);
|
||||||
})
|
})
|
||||||
|
|
||||||
if (this.selectedIndex < 0) {
|
// if (this.selectedIndex < 0) {
|
||||||
this.selectedIndex = segmentedControl.selectedSegmentIndex;
|
// this.selectedIndex = segmentedControl.selectedSegmentIndex;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ export class TabViewBase extends View implements TabViewDefinition, AddChildFrom
|
|||||||
}
|
}
|
||||||
this.items.push(<TabViewItemBase>value);
|
this.items.push(<TabViewItemBase>value);
|
||||||
this._addView(value);
|
this._addView(value);
|
||||||
|
selectedIndexProperty.coerce(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,11 +358,6 @@ export class TabView extends TabViewBase {
|
|||||||
const tv = tabLayout.getTextViewForItemAt(i);
|
const tv = tabLayout.getTextViewForItemAt(i);
|
||||||
item.setNativeView(tv);
|
item.setNativeView(tv);
|
||||||
});
|
});
|
||||||
|
|
||||||
let selectedIndex = this.selectedIndex;
|
|
||||||
if (selectedIndex < 0) {
|
|
||||||
this.selectedIndex = this._viewPager.getCurrentItem();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get [androidOffscreenTabLimitProperty.native](): number {
|
get [androidOffscreenTabLimitProperty.native](): number {
|
||||||
|
@ -268,10 +268,6 @@ export class TabView extends TabViewBase {
|
|||||||
|
|
||||||
// When we set this._ios.viewControllers, someone is clearing the moreNavigationController.delegate, so we have to reassign it each time here.
|
// When we set this._ios.viewControllers, someone is clearing the moreNavigationController.delegate, so we have to reassign it each time here.
|
||||||
this._ios.moreNavigationController.delegate = this._moreNavigationControllerDelegate;
|
this._ios.moreNavigationController.delegate = this._moreNavigationControllerDelegate;
|
||||||
|
|
||||||
if (this.selectedIndex < 0) {
|
|
||||||
this.selectedIndex = this._ios.selectedIndex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getIconRenderingMode(): UIImageRenderingMode {
|
private _getIconRenderingMode(): UIImageRenderingMode {
|
||||||
|
Reference in New Issue
Block a user