mirror of
https://dev.s-ul.net/Galexion/MaiMaiDXNet.git
synced 2024-11-27 23:00:49 +01:00
please end my web dev suffering
This commit is contained in:
parent
74e99c500f
commit
def07b872e
@ -73,7 +73,7 @@ function padNumber(num, size) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSongInformation(musicData,id) {
|
async function getSongInformation(musicData, id) {
|
||||||
const songMatch = musicData[id];
|
const songMatch = musicData[id];
|
||||||
if (!songMatch) {
|
if (!songMatch) {
|
||||||
return null;
|
return null;
|
||||||
@ -89,13 +89,13 @@ if (userdata.ban_state !== 0) {
|
|||||||
const parent = document.getElementById("User");
|
const parent = document.getElementById("User");
|
||||||
const wrapperDiv = document.createElement("div");
|
const wrapperDiv = document.createElement("div");
|
||||||
wrapperDiv.id = 'wrapper';
|
wrapperDiv.id = 'wrapper';
|
||||||
const newDiv = document.createElement("div");
|
const scoreDiv = document.createElement("div");
|
||||||
newDiv.classList.add('error')
|
scoreDiv.classList.add('error')
|
||||||
newDiv.innerHTML = `<h3 style='
|
scoreDiv.innerHTML = `<h3 style='
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
max-width:800px;'>Heya! It looks like you've been banned from playing on this profile, but don't worry - you can still enjoy the game in guest mode and view this profile. However, your account won't be able to play on it anymore. If you have any questions about your ban, please contact your Network Administrator.</h3>`; // or set the HTML content with newDiv.innerHTML = "<p>This is some HTML content</p>;
|
max-width:800px;'>Heya! It looks like you've been banned from playing on this profile, but don't worry - you can still enjoy the game in guest mode and view this profile. However, your account won't be able to play on it anymore. If you have any questions about your ban, please contact your Network Administrator.</h3>`; // or set the HTML content with scoreDiv.innerHTML = "<p>This is some HTML content</p>;
|
||||||
parent.insertBefore(wrapperDiv, parent.firstChild);
|
parent.insertBefore(wrapperDiv, parent.firstChild);
|
||||||
wrapperDiv.appendChild(newDiv);
|
wrapperDiv.appendChild(scoreDiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -149,6 +149,7 @@ let displayedScoreCount = 20;
|
|||||||
|
|
||||||
async function userPlayLogFormatter(div, loadMoreButton) {
|
async function userPlayLogFormatter(div, loadMoreButton) {
|
||||||
const UserPlayLogData = await UserPlayLog(aime_card_id);
|
const UserPlayLogData = await UserPlayLog(aime_card_id);
|
||||||
|
console.log(UserPlayLogData)
|
||||||
let scoresWrapperDiv = document.getElementById("scoreWrapper");
|
let scoresWrapperDiv = document.getElementById("scoreWrapper");
|
||||||
|
|
||||||
// If the scores wrapper div doesn't exist, create it.
|
// If the scores wrapper div doesn't exist, create it.
|
||||||
@ -158,18 +159,23 @@ async function userPlayLogFormatter(div, loadMoreButton) {
|
|||||||
div.appendChild(scoresWrapperDiv);
|
div.appendChild(scoresWrapperDiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const startIndex = scoresWrapperDiv.children.length;
|
||||||
|
if (startIndex > 0) {
|
||||||
|
// If the scores wrapper div already has children, don't do anything.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the user's play log data and music IDs.
|
// Get the user's play log data and music IDs.
|
||||||
const musicIds = UserPlayLogData.map(score => score.music_id);
|
const musicIds = UserPlayLogData.map(score => score.music_id);
|
||||||
const musicData = await musicMetadata();
|
const musicData = await musicMetadata();
|
||||||
|
|
||||||
let errorIncrement = 0;
|
let errorIncrement = 0;
|
||||||
let scoreIncrement = 0;
|
let scoreIncrement = 0;
|
||||||
const startIndex = scoresWrapperDiv.children.length;
|
for (let i = UserPlayLogData.length - 1; i >= 0; i--) {
|
||||||
const maxScores = startIndex + 20;
|
const scoreDiv = document.createElement('div'); // Create a Div
|
||||||
for (let i = startIndex; i < UserPlayLogData.length && scoreIncrement < maxScores; i++) {
|
|
||||||
const newDiv = document.createElement('div'); // Create a Div
|
|
||||||
let score = JSON.parse(JSON.stringify(UserPlayLogData[i])); // get score data
|
let score = JSON.parse(JSON.stringify(UserPlayLogData[i])); // get score data
|
||||||
let song = await getSongInformation(musicData, score.music_id) // get song data
|
let song = await getSongInformation(musicData, score.music_id) // get song data
|
||||||
|
let diffucultyData = song.difficultys.Notes[score.level] // get difficulty information
|
||||||
|
|
||||||
if (!song || !song.name) { // if a song can't be found, skip it and increment the error counter by 1.
|
if (!song || !song.name) { // if a song can't be found, skip it and increment the error counter by 1.
|
||||||
console.log(song)
|
console.log(song)
|
||||||
@ -179,29 +185,69 @@ async function userPlayLogFormatter(div, loadMoreButton) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
newDiv.innerHTML = `
|
scoreDiv.innerHTML = `
|
||||||
|
<div class="score-title">
|
||||||
<h4>${song.name.str || ""} || </h4>
|
<h4>${song.name.str || ""} || </h4>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
/* Score Jacket Image */
|
||||||
|
const scoreJacketDiv = document.createElement('div');
|
||||||
let jacket = document.createElement('img');
|
let jacket = document.createElement('img');
|
||||||
jacket.addEventListener("error", function () {
|
jacket.addEventListener("error", function () {
|
||||||
this.src = "assets/icon/UI_Icon_000000.png";
|
this.src = "assets/icon/UI_Icon_000000.png";
|
||||||
});
|
});
|
||||||
|
scoreJacketDiv.classList.add('score-jacket');
|
||||||
jacket.classList.add('score-jacket');
|
jacket.classList.add('score-jacket');
|
||||||
jacket.src = "assets/jacket/UI_Jacket_" + padNumber(Number(score.music_id), 6) + '.png';
|
jacket.src = "assets/jacket/UI_Jacket_" + padNumber(Number(score.music_id), 6) + '.png';
|
||||||
newDiv.append(jacket)
|
scoreJacketDiv.append(jacket)
|
||||||
|
scoreDiv.append(scoreJacketDiv)
|
||||||
|
|
||||||
newDiv.setAttribute("id", "score-grid");
|
/* Achivement Box */
|
||||||
newDiv.setAttribute("class", "item");
|
const scoreAchivementDiv = document.createElement('div');
|
||||||
|
scoreAchivementDiv.classList.add('score-achivement');
|
||||||
|
scoreAchivementDiv.innerHTML = `<h5>ACHIVEMENT</h5>`;
|
||||||
|
let achivementPercentage = document.createElement('h5');
|
||||||
|
let achivementNumber = padNumber(Number(score.achievement), 7)
|
||||||
|
achivementPercentage.textContent = `${achivementNumber / 10000}%`;
|
||||||
|
scoreAchivementDiv.append(achivementPercentage)
|
||||||
|
scoreDiv.append(scoreAchivementDiv)
|
||||||
|
|
||||||
|
/* Score Grade */
|
||||||
|
let scoreGrades = ["D", "C", "B", "BB", "BBB", "A", "AA", "AAA", "S", "S+", "SS", "SS+", "SSS", "SSS+"]
|
||||||
|
const scoreGradeDiv = document.createElement('div');
|
||||||
|
scoreGradeDiv.classList.add('score-grade');
|
||||||
|
let scoreGrade = document.createElement('h4');
|
||||||
|
scoreGrade.textContent = `${scoreGrades[score.score_rank]}`;
|
||||||
|
scoreGradeDiv.append(scoreGrade);
|
||||||
|
scoreDiv.append(scoreGradeDiv);
|
||||||
|
|
||||||
|
/* DX Score, Full Combo, Full Sync, and Multi-Placement */
|
||||||
|
|
||||||
|
const scoreInfoDiv = document.createElement('div');
|
||||||
|
scoreInfoDiv.classList.add('score-info');
|
||||||
|
const scoreInfoGridDiv = document.createElement('div');
|
||||||
|
scoreInfoDiv.classList.add('score-info-grid');
|
||||||
|
// please i dont want to make a fucking nested grid
|
||||||
|
/* DX Score */
|
||||||
|
const scoreDXScoreDiv = document.createElement('div');
|
||||||
|
scoreDXScoreDiv.classList.add('DX-Score');
|
||||||
|
scoreDXScoreDiv.innerHTML = `<h4>DX Score: ${score.deluxscore} / ${diffucultyData.maxNotes * 3}</h4>`;
|
||||||
|
scoreInfoGridDiv.append(scoreDXScoreDiv);
|
||||||
|
scoreInfoDiv.append(scoreInfoGridDiv);
|
||||||
|
scoreDiv.append(scoreInfoDiv);
|
||||||
|
|
||||||
|
|
||||||
|
scoreDiv.setAttribute("class", "score-grid");
|
||||||
scoreIncrement++
|
scoreIncrement++
|
||||||
|
|
||||||
scoresWrapperDiv.appendChild(newDiv);
|
scoresWrapperDiv.appendChild(scoreDiv);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Edit the Score Info Header with the relevant information.
|
// Edit the Score Info Header with the relevant information.
|
||||||
const header = document.querySelector('#score-info-header');
|
const header = document.querySelector('#score-info-header');
|
||||||
header.textContent = `Showing ${startIndex + scoreIncrement - errorIncrement} out of ${UserPlayLogData.length} scores.`;
|
header.textContent = `Showing ${startIndex + scoreIncrement - errorIncrement} out of ${scoreIncrement} scores.`;
|
||||||
if (errorIncrement > 0) {
|
if (errorIncrement > 0) {
|
||||||
header.insertAdjacentHTML('afterend', `<p>${errorIncrement} Songs Failed to load properly, most likely due to missing information.</p>`);
|
header.insertAdjacentHTML('afterend', `<p>${errorIncrement} Songs Failed to load properly, most likely due to missing information.</p>`);
|
||||||
}
|
}
|
||||||
@ -217,6 +263,9 @@ async function userPlayLogFormatter(div, loadMoreButton) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
// Now Exiting: User Data ////////////// Now Entering: Nested Div Hell
|
// Now Exiting: User Data ////////////// Now Entering: Nested Div Hell
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
|
@ -1,88 +1,88 @@
|
|||||||
#user-image {
|
#user-image {
|
||||||
display: block;
|
display: block;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#User {
|
#User {
|
||||||
display: block;
|
display: block;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin: 1%;
|
margin: 1%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#wrapper {
|
#wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#user-profile-wrapper {
|
#user-profile-wrapper {
|
||||||
display: inline-grid;
|
display: inline-grid;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"profile-image user-title user-title"
|
"profile-image user-title user-title"
|
||||||
"profile-image user-name dx-rating"
|
"profile-image user-name dx-rating"
|
||||||
"profile-image user-class awakens";
|
"profile-image user-class awakens";
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
border: 2px solid black;
|
border: 2px solid black;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
@media screen and (max-width: 768px) {
|
||||||
#user-profile-wrapper {
|
#user-profile-wrapper {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: 2px solid black;
|
border: 2px solid black;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-image {
|
.profile-image {
|
||||||
grid-area: profile-image;
|
grid-area: profile-image;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-title {
|
.user-title {
|
||||||
grid-area: user-title;
|
grid-area: user-title;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-name {
|
.user-name {
|
||||||
grid-area: user-name;
|
grid-area: user-name;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dx-rating {
|
.dx-rating {
|
||||||
grid-area: dx-rating;
|
grid-area: dx-rating;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-rank {
|
.user-rank {
|
||||||
grid-area: user-rank;
|
grid-area: user-rank;
|
||||||
}
|
}
|
||||||
|
|
||||||
.awakens {
|
.awakens {
|
||||||
grid-area: awakens;
|
grid-area: awakens;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4.profile {
|
h4.profile {
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
h4 {
|
h4 {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
@ -95,100 +95,131 @@ h4.profile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.buttons {
|
.buttons {
|
||||||
margin-bottom: 2em;
|
margin-bottom: 2em;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"1a 2b 3c 4d"
|
"1a 2b 3c 4d"
|
||||||
"5e 6f 7g 8h";
|
"5e 6f 7g 8h";
|
||||||
grid-gap: 10px;
|
grid-gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn1 {
|
|
||||||
grid-area: "1a";
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn2 {
|
|
||||||
grid-area: "2b";
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn3 {
|
|
||||||
grid-area: "3c";
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn4 {
|
|
||||||
grid-area: "4d";
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn5 {
|
|
||||||
grid-area: "5e";
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn6 {
|
|
||||||
grid-area: "6f";
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn7 {
|
|
||||||
grid-area: "7g";
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn8 {
|
|
||||||
grid-area: "8h";
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display:none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Jacket Grid */
|
.btn1 {
|
||||||
|
grid-area: "1a";
|
||||||
|
}
|
||||||
|
|
||||||
.score-grid {
|
.btn2 {
|
||||||
display: grid;
|
grid-area: "2b";
|
||||||
|
}
|
||||||
grid-template-rows: 1fr 1fr 1fr;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
.btn3 {
|
||||||
|
grid-area: "3c";
|
||||||
grid-template-areas:
|
}
|
||||||
'label0 label0 label0 label0'
|
|
||||||
'label1 label1 label2 label3'
|
.btn4 {
|
||||||
'label1 label1 label4 label4';
|
grid-area: "4d";
|
||||||
|
}
|
||||||
gap: 0px;
|
|
||||||
height: 100%;
|
.btn5 {
|
||||||
|
grid-area: "5e";
|
||||||
}
|
}
|
||||||
|
|
||||||
.score-title {
|
.btn6 {
|
||||||
|
grid-area: "6f";
|
||||||
background-color: #D5BBCA;
|
}
|
||||||
grid-area: label0;
|
|
||||||
|
.btn7 {
|
||||||
}
|
grid-area: "7g";
|
||||||
.score-jacket {
|
}
|
||||||
|
|
||||||
background-color: #9EF6B5;
|
.btn8 {
|
||||||
grid-area: label1;
|
grid-area: "8h";
|
||||||
display: block;
|
}
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
.hidden {
|
||||||
max-width: 25%;
|
display: none !important;
|
||||||
width: 25%;
|
}
|
||||||
|
|
||||||
}
|
/* Play Data CSS */
|
||||||
.score-achivement {
|
|
||||||
|
#score-info-header-div {
|
||||||
background-color: #ED69FD;
|
grid-area: 2 / 2 / 3 / 4;
|
||||||
grid-area: label2;
|
}
|
||||||
|
|
||||||
}
|
#scoreWrapper {
|
||||||
.score-grade {
|
grid-area: 3 / 2 / 4 / 4;
|
||||||
|
width:auto;
|
||||||
background-color: #9B5999;
|
align-items: start;
|
||||||
grid-area: label3;
|
justify-items: start;
|
||||||
|
}
|
||||||
}
|
|
||||||
.score-info {
|
|
||||||
|
.score-grid {
|
||||||
background-color: #58B669;
|
display: grid;
|
||||||
grid-area: label4;
|
|
||||||
|
grid-template-rows: min-content min-content 1fr;
|
||||||
}
|
grid-template-columns: 300px 300px 5em;
|
||||||
|
|
||||||
|
grid-template-areas:
|
||||||
|
'label0 label0 label0'
|
||||||
|
'label1 label2 label3'
|
||||||
|
'label1 label4 label4';
|
||||||
|
|
||||||
|
gap: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.score-title {
|
||||||
|
|
||||||
|
background-color: #D5BBCA;
|
||||||
|
grid-area: label0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.score-jacket {
|
||||||
|
|
||||||
|
background-color: #9EF6B5;
|
||||||
|
grid-area: label1;
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.score-achivement {
|
||||||
|
|
||||||
|
background-color: #ED69FD;
|
||||||
|
grid-area: label2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.score-grade {
|
||||||
|
|
||||||
|
background-color: #9B5999;
|
||||||
|
grid-area: label3;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.score-info {
|
||||||
|
|
||||||
|
background-color: #58B669;
|
||||||
|
grid-area: label4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Please I really dont want to make a nested grid */
|
||||||
|
.score-info-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
grid-template-rows: repeat(3, 1fr);
|
||||||
|
grid-gap: 10px;
|
||||||
|
grid-template-areas:
|
||||||
|
"DX-Score DX-Score DX-Score"
|
||||||
|
"full-combo full-sync multi-place"
|
||||||
|
"details details details";
|
||||||
|
}
|
||||||
|
|
||||||
|
.DX-Score {
|
||||||
|
grid-area: DX-Score;
|
||||||
|
}
|
@ -40,6 +40,7 @@ ToDo:
|
|||||||
- Get User Playlog Data (Done)
|
- Get User Playlog Data (Done)
|
||||||
- Sort From Most Recent (Done)
|
- Sort From Most Recent (Done)
|
||||||
- Assign Song Names to Each Score (done)
|
- Assign Song Names to Each Score (done)
|
||||||
|
- Re-Create the MaiMaiDXNet Playlog list (Partially Done)
|
||||||
- Create Detailed Look Into Score
|
- Create Detailed Look Into Score
|
||||||
- Create Photos Tab
|
- Create Photos Tab
|
||||||
- Create Area Tab
|
- Create Area Tab
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<link href="/stylesheets/user.css" rel="stylesheet" type="text/css">
|
<link href="/stylesheets/user.css" rel="stylesheet" type="text/css">
|
||||||
<div id="User">
|
<div id="User">
|
||||||
<h1>Yo! Welcome Back <%= normalizeText(userdata.user_name) %>!</h1>
|
<h1>Yo! Welcome Back <%= normalizeText(userdata.user_name) %>!</h1>
|
||||||
|
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<!-- Calm before the storm -->
|
<!-- Calm before the storm -->
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
@ -36,10 +36,13 @@
|
|||||||
<h4>★ ☓<%= userdata.total_awake%></h4>
|
<h4>★ ☓<%= userdata.total_awake%></h4>
|
||||||
</div>
|
</div>
|
||||||
</div><!-- This is just one nested div, Trmazi it's going to get a lot worse from here on. -->
|
</div><!-- This is just one nested div, Trmazi it's going to get a lot worse from here on. -->
|
||||||
<div data-content="content-2" id="user-play-data" class="hidden"> <!-- User Play-Log is generated at run time when the user clicks the button, so they get up to date data. -->
|
<div data-content="content-2" id="user-play-data" class="hidden">
|
||||||
<h4 id="score-info-header">Please Wait, Obtaining Scores...</h4>
|
<!-- User Play-Log is generated at run time when the user clicks the button, so they get up to date data. -->
|
||||||
|
<div id="score-info-header-div">
|
||||||
|
<h4 id="score-info-header">Please Wait, Obtaining Scores...</h4>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user