More animations
This commit is contained in:
parent
722f372a01
commit
80ede11f7c
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
server/node_modules/
|
server/node_modules/
|
||||||
client/node_modules/
|
client/node_modules/
|
||||||
|
node_modules/
|
||||||
server/dist/
|
server/dist/
|
||||||
client/dist/
|
client/dist/
|
||||||
|
|
||||||
|
@ -221,6 +221,17 @@ button:active {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.document.item {
|
||||||
|
text-align: center;
|
||||||
|
width: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.document.item img {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.document h1 {
|
.document h1 {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
|
@ -8,7 +8,10 @@ let cursorY = 0;
|
|||||||
|
|
||||||
let arrowIcon = "icons/iconoir/regular/nav-arrow-right.svg";
|
let arrowIcon = "icons/iconoir/regular/nav-arrow-right.svg";
|
||||||
|
|
||||||
|
import { animate } from 'motion'
|
||||||
|
|
||||||
function Show(){
|
function Show(){
|
||||||
|
console.log("SHOW")
|
||||||
let contextMenu = document.getElementById('context-menu');
|
let contextMenu = document.getElementById('context-menu');
|
||||||
contextMenu.style.display = "flex";
|
contextMenu.style.display = "flex";
|
||||||
contextMenu.style.top = (cursorY + margin) + "px";
|
contextMenu.style.top = (cursorY + margin) + "px";
|
||||||
@ -22,6 +25,8 @@ function HideContextMenu(){
|
|||||||
|
|
||||||
function PopulateContext(val){
|
function PopulateContext(val){
|
||||||
let children = [];
|
let children = [];
|
||||||
|
|
||||||
|
let elementNum = 0;
|
||||||
val.forEach(element => {
|
val.forEach(element => {
|
||||||
let contextMenuElement = document.createElement('div');
|
let contextMenuElement = document.createElement('div');
|
||||||
contextMenuElement.classList.add("context-menu-element");
|
contextMenuElement.classList.add("context-menu-element");
|
||||||
@ -64,6 +69,14 @@ function PopulateContext(val){
|
|||||||
}
|
}
|
||||||
|
|
||||||
children.push(contextMenuElement);
|
children.push(contextMenuElement);
|
||||||
|
|
||||||
|
animate(contextMenuElement, {
|
||||||
|
opacity: [0, 1],
|
||||||
|
translateY: [20, -2]
|
||||||
|
}, {delay: (elementNum / 2) * 0.1, duration: 0.25}).finished.then(() => {
|
||||||
|
|
||||||
|
});
|
||||||
|
elementNum++;
|
||||||
});
|
});
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
|
@ -1,19 +1,42 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { animate } from 'motion';
|
||||||
|
|
||||||
let content = ref("");
|
let content = ref("");
|
||||||
let margin = 14;
|
let margin = 14;
|
||||||
|
|
||||||
let cursorX = 0;
|
let cursorX = 0;
|
||||||
let cursorY = 0;
|
let cursorY = 0;1
|
||||||
|
|
||||||
|
let showed = false;
|
||||||
|
let hided = false;
|
||||||
|
|
||||||
function ShowTooltip(){
|
function ShowTooltip(){
|
||||||
let tooltip = document.getElementById('mouse-tooltip');
|
let tooltip = document.getElementById('mouse-tooltip');
|
||||||
|
|
||||||
tooltip.style.display = "block";
|
tooltip.style.display = "block";
|
||||||
|
|
||||||
|
if(!showed){
|
||||||
|
animate(tooltip, {
|
||||||
|
opacity: [0, 1],
|
||||||
|
translateY: [20, 0]
|
||||||
|
}, {duration: 0.1, ease: 'ease-out'});
|
||||||
|
showed = true;
|
||||||
|
hided = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function HideTooltip(){
|
function HideTooltip(){
|
||||||
let tooltip = document.getElementById('mouse-tooltip');
|
let tooltip = document.getElementById('mouse-tooltip');
|
||||||
tooltip.style.display = "none";
|
|
||||||
|
|
||||||
|
if(!hided){
|
||||||
|
animate(tooltip, {
|
||||||
|
opacity: [1, 0],
|
||||||
|
translateY: [0, 20]
|
||||||
|
}, {duration: 0.1, ease: 'ease-in'}).finished.then(() => tooltip.style.display = "none")
|
||||||
|
hided = true;
|
||||||
|
showed = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddTooltip(element, val, data = {}){
|
function AddTooltip(element, val, data = {}){
|
||||||
@ -22,13 +45,21 @@ function AddTooltip(element, val, data = {}){
|
|||||||
|
|
||||||
function UpdateVisibilityThread(){
|
function UpdateVisibilityThread(){
|
||||||
let tooltip = document.getElementById('mouse-tooltip');
|
let tooltip = document.getElementById('mouse-tooltip');
|
||||||
let element = document.elementFromPoint(cursorX, cursorY);
|
let elements = document.elementsFromPoint(cursorX, cursorY);
|
||||||
if(element) if(element._dr_tooltip){
|
|
||||||
ShowTooltip();
|
let visible = false;
|
||||||
content.value = element._dr_tooltip.value;
|
for(let i = 0; i < elements.length; i++){
|
||||||
if(element._dr_tooltip.max_width) tooltip.style.maxWidth = element._dr_tooltip.max_width + "px";
|
let element = elements[i];
|
||||||
else tooltip.style.maxWidth = "none";
|
if(element._dr_tooltip){
|
||||||
} else HideTooltip();
|
ShowTooltip();
|
||||||
|
content.value = element._dr_tooltip.value;
|
||||||
|
if(element._dr_tooltip.max_width) tooltip.style.maxWidth = element._dr_tooltip.max_width + "px";
|
||||||
|
else tooltip.style.maxWidth = "none";
|
||||||
|
visible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!visible) HideTooltip();
|
||||||
|
|
||||||
setTimeout(UpdateVisibilityThread, 0);
|
setTimeout(UpdateVisibilityThread, 0);
|
||||||
}
|
}
|
||||||
|
@ -35,18 +35,18 @@ onMounted(() => {
|
|||||||
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
background-color: var(--tooltip-background);
|
|
||||||
|
|
||||||
-webkit-box-shadow: 0px 0px 5px -2px rgba(0,0,0,0.75);
|
|
||||||
-moz-box-shadow: 0px 0px 5px -2px rgba(0,0,0,0.75);
|
|
||||||
box-shadow: 0px 0px 5px -2px rgba(0,0,0,0.75);
|
|
||||||
|
|
||||||
border: solid 1px var(--color-border);
|
|
||||||
|
|
||||||
.context-menu-element {
|
.context-menu-element {
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-width: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
border: solid 1px var(--color-border);
|
||||||
|
border-width: 1px 1px 0px 1px;
|
||||||
padding: 3px 5px 3px 5px;
|
padding: 3px 5px 3px 5px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
background-color: var(--tooltip-background);
|
||||||
transition: background-color 100ms;
|
transition: background-color 100ms;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
73
client/src/views/partials/ConceptEntry.vue
Normal file
73
client/src/views/partials/ConceptEntry.vue
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<script setup>
|
||||||
|
import { onMounted, ref, watch } from 'vue';
|
||||||
|
import { AddContextMenu } from '@/services/ContextMenu';
|
||||||
|
import { AddTooltip } from '@/services/Tooltip';
|
||||||
|
import { marked } from "https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js";
|
||||||
|
|
||||||
|
const props = defineProps(['element']);
|
||||||
|
|
||||||
|
const element = ref({});
|
||||||
|
const elementDiv = ref(null);
|
||||||
|
const tooltipContainer = ref(null);
|
||||||
|
|
||||||
|
function updateElement(){
|
||||||
|
element.value = props.element;
|
||||||
|
// Do whatever
|
||||||
|
let desc = element.value.info.description;
|
||||||
|
desc = desc ? marked.parse(desc) : '';
|
||||||
|
console.log(desc);
|
||||||
|
AddTooltip(tooltipContainer.value, `<div class='document item'>
|
||||||
|
<h2>${element.value.name}</h2>
|
||||||
|
<img src='${element.value.info.icon}'></img>
|
||||||
|
<div class='document'>${desc}</div>
|
||||||
|
</div>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
updateElement();
|
||||||
|
watch(() => props.element, () => {
|
||||||
|
updateElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
AddContextMenu(elementDiv.value, [
|
||||||
|
{name: "Open"},
|
||||||
|
{name: "Delete"}
|
||||||
|
]);
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="concept-element" ref="elementDiv">
|
||||||
|
<div class="concept-tooltip-container" ref="tooltipContainer">
|
||||||
|
<img :src="element.info ? element.info.icon : 'icons/game-icons/ffffff/lorc/crossed-swords.svg'" class="concept-icon">
|
||||||
|
<span class="title">{{ element.name }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style lang="scss">
|
||||||
|
.concept-tooltip-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.concept-icon {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.concept-element {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid var(--color-border-soft);
|
||||||
|
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding-left: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,9 +1,11 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
import { onMounted, ref, watch } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
import { GetCampaign } from '../../services/Dragonroll';
|
import { GetCampaign } from '../../services/Dragonroll';
|
||||||
import { ClearWindow, CreateWindow } from '../../services/Windows';
|
import { ClearWindow, CreateWindow } from '../../services/Windows';
|
||||||
|
|
||||||
|
import { animate } from "motion"
|
||||||
|
import ConceptEntry from './ConceptEntry.vue';
|
||||||
|
|
||||||
const props = defineProps(['elements']);
|
const props = defineProps(['elements']);
|
||||||
|
|
||||||
const listContainer = ref(null);
|
const listContainer = ref(null);
|
||||||
@ -17,64 +19,41 @@ onMounted(() => {
|
|||||||
|
|
||||||
function OpenConcept(element){
|
function OpenConcept(element){
|
||||||
CreateWindow('item_sheet', {
|
CreateWindow('item_sheet', {
|
||||||
id: 'item_sheet',
|
id: 'item_sheet_' + element._id,
|
||||||
title: 'Edit Item',
|
title: 'Edit Item',
|
||||||
item_id: element._id,
|
item_id: element._id,
|
||||||
close: () => ClearWindow('item_sheet')
|
close: () => ClearWindow('item_sheet_' + element._id)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onBeforeEnter(el) {
|
||||||
|
el.style.opacity = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEnter(el, done) {
|
||||||
|
animate(el, {
|
||||||
|
opacity: [0, 1],
|
||||||
|
translateX: [20, 0]
|
||||||
|
}, {delay: el.dataset.index * 0.025})
|
||||||
|
}
|
||||||
|
|
||||||
|
function onLeave(el, done) {
|
||||||
|
animate(el, {
|
||||||
|
opacity: [1, 0],
|
||||||
|
translateX: [0, 20]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="list-container" ref="listContainer">
|
<div class="list-container" ref="listContainer">
|
||||||
<TransitionGroup name="list-element">
|
<TransitionGroup name="list-element" :css="false" @before-enter="onBeforeEnter" @enter="onEnter" @leave="onLeave">
|
||||||
<div class="list-element" v-for="element in elements" :key="element._id" v-on:click.prevent="OpenConcept(element)">
|
<ConceptEntry class="list-element" v-for="(element, index) in elements" :key="element._id" :element="element" v-on:click.prevent="OpenConcept(element)" :data-index="index"></ConceptEntry>
|
||||||
<img :src="element.info ? element.info.icon : 'icons/game-icons/ffffff/lorc/crossed-swords.svg'" class="concept-icon">
|
|
||||||
<span class="title">{{ element.name }}</span>
|
|
||||||
</div>
|
|
||||||
</TransitionGroup>
|
</TransitionGroup>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.concept-icon {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-element {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
padding: 10px;
|
|
||||||
align-items: center;
|
|
||||||
border-bottom: 1px solid var(--color-border-soft);
|
|
||||||
|
|
||||||
|
|
||||||
.title {
|
|
||||||
padding-left: 10px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-element-move, /* apply transition to moving elements */
|
|
||||||
.list-element-enter-active,
|
|
||||||
.list-element-leave-active {
|
|
||||||
transition: all 0.5s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-element-enter-from,
|
|
||||||
.list-element-leave-to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(30px);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ensure leaving items are taken out of layout flow so that moving
|
|
||||||
animations can be calculated correctly. */
|
|
||||||
.list-element-leave-active {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-container {
|
.list-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -68,6 +68,7 @@ function SelectTab(row){
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-content-inner {
|
.tab-content-inner {
|
||||||
|
100
package-lock.json
generated
100
package-lock.json
generated
@ -1,6 +1,104 @@
|
|||||||
{
|
{
|
||||||
"name": "dragonroll",
|
"name": "dragonroll",
|
||||||
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {}
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "dragonroll",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"motion": "^10.18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/animation": {
|
||||||
|
"version": "10.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz",
|
||||||
|
"integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/easing": "^10.18.0",
|
||||||
|
"@motionone/types": "^10.17.1",
|
||||||
|
"@motionone/utils": "^10.18.0",
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/dom": {
|
||||||
|
"version": "10.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.18.0.tgz",
|
||||||
|
"integrity": "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/animation": "^10.18.0",
|
||||||
|
"@motionone/generators": "^10.18.0",
|
||||||
|
"@motionone/types": "^10.17.1",
|
||||||
|
"@motionone/utils": "^10.18.0",
|
||||||
|
"hey-listen": "^1.0.8",
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/easing": {
|
||||||
|
"version": "10.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz",
|
||||||
|
"integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/utils": "^10.18.0",
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/generators": {
|
||||||
|
"version": "10.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz",
|
||||||
|
"integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/types": "^10.17.1",
|
||||||
|
"@motionone/utils": "^10.18.0",
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/types": {
|
||||||
|
"version": "10.17.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz",
|
||||||
|
"integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/utils": {
|
||||||
|
"version": "10.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz",
|
||||||
|
"integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/types": "^10.17.1",
|
||||||
|
"hey-listen": "^1.0.8",
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hey-listen": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/motion": {
|
||||||
|
"version": "10.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion/-/motion-10.18.0.tgz",
|
||||||
|
"integrity": "sha512-MVAZZmwM/cp77BrNe1TxTMldxRPjwBNHheU5aPToqT4rJdZxLiADk58H+a0al5jKLxkB0OdgNq6DiVn11cjvIQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/animation": "^10.18.0",
|
||||||
|
"@motionone/dom": "^10.18.0",
|
||||||
|
"@motionone/types": "^10.17.1",
|
||||||
|
"@motionone/utils": "^10.18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
|
||||||
|
"license": "0BSD"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,5 +7,8 @@
|
|||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"author": "Aran Roig",
|
"author": "Aran Roig",
|
||||||
"license": "ISC"
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"motion": "^10.18.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user