Add board model detection
This commit is contained in:
parent
d59f4818b4
commit
b10d6da3e1
106
core.js
106
core.js
@ -28,36 +28,74 @@ function dec2hex8(i) {
|
|||||||
return (i+0x100).toString(16).substr(-2).toUpperCase();
|
return (i+0x100).toString(16).substr(-2).toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ds4_hw_to_bm(hw_ver) {
|
||||||
|
a = hw_ver >> 8;
|
||||||
|
if(a == 0x31) {
|
||||||
|
return "JDM-001";
|
||||||
|
} else if(a == 0x43) {
|
||||||
|
return "JDM-011";
|
||||||
|
} else if(a == 0x54) {
|
||||||
|
return "JDM-030";
|
||||||
|
} else if(a == 0x64) {
|
||||||
|
return "JDM-040";
|
||||||
|
} else if(a == 0xa4) {
|
||||||
|
return "JDM-050";
|
||||||
|
} else if(a == 0xb4) {
|
||||||
|
return "JDM-055";
|
||||||
|
} else {
|
||||||
|
return l("Unknown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function ds4_info() {
|
async function ds4_info() {
|
||||||
const view = await device.receiveFeatureReport(0xa3);
|
|
||||||
|
|
||||||
var cmd = view.getUint8(0, true);
|
|
||||||
if(cmd != 0xa3 || view.buffer.byteLength != 49)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var k1 = new TextDecoder().decode(view.buffer.slice(1, 0x10));
|
|
||||||
var k2 = new TextDecoder().decode(view.buffer.slice(0x10, 0x20));
|
|
||||||
k1=k1.replace(/\0/g, '');
|
|
||||||
k2=k2.replace(/\0/g, '');
|
|
||||||
|
|
||||||
var hw_ver_major= view.getUint16(0x21, true)
|
|
||||||
var hw_ver_minor= view.getUint16(0x23, true)
|
|
||||||
var sw_ver_major= view.getUint32(0x25, true)
|
|
||||||
var sw_ver_minor= view.getUint16(0x25+4, true)
|
|
||||||
var ooc = l("unknown");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const view = await device.receiveFeatureReport(0x81);
|
const view = await device.receiveFeatureReport(0xa3);
|
||||||
|
|
||||||
|
var cmd = view.getUint8(0, true);
|
||||||
|
if(cmd != 0xa3 || view.buffer.byteLength != 49)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var k1 = new TextDecoder().decode(view.buffer.slice(1, 0x10));
|
||||||
|
var k2 = new TextDecoder().decode(view.buffer.slice(0x10, 0x20));
|
||||||
|
k1=k1.replace(/\0/g, '');
|
||||||
|
k2=k2.replace(/\0/g, '');
|
||||||
|
|
||||||
|
var hw_ver_major= view.getUint16(0x21, true)
|
||||||
|
var hw_ver_minor= view.getUint16(0x23, true)
|
||||||
|
var sw_ver_major= view.getUint32(0x25, true)
|
||||||
|
var sw_ver_minor= view.getUint16(0x25+4, true)
|
||||||
|
var ooc = l("unknown");
|
||||||
|
|
||||||
ooc = l("original");
|
ooc = l("original");
|
||||||
|
|
||||||
|
var is_clone = false;
|
||||||
|
try {
|
||||||
|
const view = await device.receiveFeatureReport(0x81);
|
||||||
|
ooc = l("original");
|
||||||
|
} catch(e) {
|
||||||
|
is_clone = true;
|
||||||
|
ooc = "<font color='red'><b>" + l("clone") + "</b></font>";
|
||||||
|
disable_btn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_info();
|
||||||
|
append_info(l("Build Date:"), k1 + " " + k2);
|
||||||
|
append_info(l("HW Version:"), "" + dec2hex(hw_ver_major) + ":" + dec2hex(hw_ver_minor));
|
||||||
|
append_info(l("SW Version:"), dec2hex32(sw_ver_major) + ":" + dec2hex(sw_ver_minor));
|
||||||
|
append_info(l("Device Type:"), ooc);
|
||||||
|
if(!is_clone) {
|
||||||
|
b_info = ' <a class="link-body-emphasis" href="#" onclick="board_model_info()">' +
|
||||||
|
'<svg class="bi" width="1.3em" height="1.3em"><use xlink:href="#info"/></svg></a>';
|
||||||
|
append_info(l("Board Model:"), ds4_hw_to_bm(hw_ver_minor) + b_info);
|
||||||
|
|
||||||
|
// All ok, safe to query NVS Status and BD Addr
|
||||||
|
await ds4_nvstatus();
|
||||||
|
await ds4_getbdaddr();
|
||||||
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
ooc = "<font color='red'><b>" + l("clone") + "</b></font>";
|
ooc = "<font color='red'><b>" + l("clone") + "</b></font>";
|
||||||
disable_btn = true;
|
disable_btn = true;
|
||||||
}
|
}
|
||||||
clear_info();
|
|
||||||
append_info(l("Build Date:"), k1 + " " + k2);
|
|
||||||
append_info(l("HW Version:"), "" + dec2hex(hw_ver_major) + ":" + dec2hex(hw_ver_minor));
|
|
||||||
append_info(l("SW Version:"), dec2hex32(sw_ver_major) + ":" + dec2hex(sw_ver_minor));
|
|
||||||
append_info(l("Device Type:"), ooc);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,6 +745,8 @@ function alloc_req(id, data=[]) {
|
|||||||
async function connect() {
|
async function connect() {
|
||||||
try {
|
try {
|
||||||
$("#btnconnect").prop("disabled", true);
|
$("#btnconnect").prop("disabled", true);
|
||||||
|
$("#connectspinner").show();
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
|
||||||
let ds4v1 = { vendorId: 0x054c, productId: 0x05c4 };
|
let ds4v1 = { vendorId: 0x054c, productId: 0x05c4 };
|
||||||
let ds4v2 = { vendorId: 0x054c, productId: 0x09cc };
|
let ds4v2 = { vendorId: 0x054c, productId: 0x09cc };
|
||||||
@ -721,11 +761,13 @@ try {
|
|||||||
|
|
||||||
if (devices.length == 0) {
|
if (devices.length == 0) {
|
||||||
$("#btnconnect").prop("disabled", false);
|
$("#btnconnect").prop("disabled", false);
|
||||||
|
$("#connectspinner").hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (devices.length > 1) {
|
if (devices.length > 1) {
|
||||||
$("#btnconnect").prop("disabled", false);
|
$("#btnconnect").prop("disabled", false);
|
||||||
|
$("#connectspinner").hide();
|
||||||
show_popup(l("Please connect only one controller at time."));
|
show_popup(l("Please connect only one controller at time."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -762,6 +804,7 @@ try {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$("#btnconnect").prop("disabled", false);
|
$("#btnconnect").prop("disabled", false);
|
||||||
|
$("#connectspinner").hide();
|
||||||
show_popup(l("Connected invalid device: ") + dec2hex(device.vendorId) + ":" + dec2hex(device.productId))
|
show_popup(l("Connected invalid device: ") + dec2hex(device.vendorId) + ":" + dec2hex(device.productId))
|
||||||
disconnect();
|
disconnect();
|
||||||
return;
|
return;
|
||||||
@ -788,8 +831,10 @@ try {
|
|||||||
$(".ds-btn").prop("disabled", disable_btn);
|
$(".ds-btn").prop("disabled", disable_btn);
|
||||||
|
|
||||||
$("#btnconnect").prop("disabled", false);
|
$("#btnconnect").prop("disabled", false);
|
||||||
|
$("#connectspinner").hide();
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
$("#btnconnect").prop("disabled", false);
|
$("#btnconnect").prop("disabled", false);
|
||||||
|
$("#connectspinner").hide();
|
||||||
show_popup(l("Error: ") + error);
|
show_popup(l("Error: ") + error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -927,8 +972,12 @@ function append_info(key, value) {
|
|||||||
$("#fwinfo").html($("#fwinfo").html() + s);
|
$("#fwinfo").html($("#fwinfo").html() + s);
|
||||||
}
|
}
|
||||||
|
|
||||||
function show_popup(text) {
|
function show_popup(text, is_html = false) {
|
||||||
$("#popupBody").text(text);
|
if(is_html) {
|
||||||
|
$("#popupBody").html(text);
|
||||||
|
} else {
|
||||||
|
$("#popupBody").text(text);
|
||||||
|
}
|
||||||
new bootstrap.Modal(document.getElementById('popupModal'), {}).show()
|
new bootstrap.Modal(document.getElementById('popupModal'), {}).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -938,6 +987,13 @@ function show_faq_modal() {
|
|||||||
|
|
||||||
function discord_popup() { show_popup(l("My handle on discord is: the_al")); }
|
function discord_popup() { show_popup(l("My handle on discord is: the_al")); }
|
||||||
|
|
||||||
|
function board_model_info() {
|
||||||
|
l1 = l("This feature is experimental.");
|
||||||
|
l2 = l("Please let me know if the board model of your controller is not detected correctly.");
|
||||||
|
l3 = l("Board model detection thanks to") + ' <a href="https://battlebeavercustoms.com/">Battle Beaver Customs</a>.';
|
||||||
|
show_popup(l3 + "<br><br>" + l1 + " " + l2, true);
|
||||||
|
}
|
||||||
|
|
||||||
function calib_perm_changes() { return $("#calibPermanentChanges").is(':checked') }
|
function calib_perm_changes() { return $("#calibPermanentChanges").is(':checked') }
|
||||||
|
|
||||||
function reset_calib_perm_changes() {
|
function reset_calib_perm_changes() {
|
||||||
|
11
index.html
11
index.html
@ -24,6 +24,9 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
|
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
|
||||||
|
<symbol id="info" viewBox="0 -860 960 960">
|
||||||
|
<path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/>
|
||||||
|
</symbol>
|
||||||
<symbol id="discord" viewBox="0 0 640 512">
|
<symbol id="discord" viewBox="0 0 640 512">
|
||||||
<path d="M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z"/>
|
<path d="M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z"/>
|
||||||
</symbol>
|
</symbol>
|
||||||
@ -79,7 +82,11 @@
|
|||||||
|
|
||||||
<div id="offlinebar" class="vstack p-2" style="display: none;">
|
<div id="offlinebar" class="vstack p-2" style="display: none;">
|
||||||
<p class="ds-i18n">Connect a DualShock 4 or a DualSense controller to your computer and press Connect.</p>
|
<p class="ds-i18n">Connect a DualShock 4 or a DualSense controller to your computer and press Connect.</p>
|
||||||
<button id="btnconnect" type="button" class="btn btn-outline-primary ds-i18n" onclick="connect()">Connect</button><br>
|
<button id="btnconnect" type="button" class="btn btn-outline-primary" onclick="connect()">
|
||||||
|
<span class="spinner-border spinner-border-sm" style="display: none;" id="connectspinner" aria-hidden="true"></span>
|
||||||
|
<span class="ds-i18n">Connect</span>
|
||||||
|
</button>
|
||||||
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="onlinebar" class="vstack p-2" style="display: none;">
|
<div id="onlinebar" class="vstack p-2" style="display: none;">
|
||||||
@ -430,7 +437,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<footer>
|
<footer>
|
||||||
<div class="d-flex flex-column flex-sm-row justify-content-between py-4 my-4 border-top" id="footbody">
|
<div class="d-flex flex-column flex-sm-row justify-content-between py-4 my-4 border-top" id="footbody">
|
||||||
<p><span class="ds-i18n">Version</span> 0.6 (2024-04-17) - <a href="#" class="ds-i18n" data-bs-toggle="modal" data-bs-target="#donateModal">Support this project</a> <span id="authorMsg"></span></p>
|
<p><span class="ds-i18n">Version</span> 0.7 (2024-04-21) - <a href="#" class="ds-i18n" data-bs-toggle="modal" data-bs-target="#donateModal">Support this project</a> <span id="authorMsg"></span></p>
|
||||||
|
|
||||||
<ul class="list-unstyled d-flex">
|
<ul class="list-unstyled d-flex">
|
||||||
<li class="ms-3"><a class="link-body-emphasis" href="mailto:ds4@the.al" target="_blank"><svg class="bi" width="24" height="24"><use xlink:href="#mail"/></svg></a></li>
|
<li class="ms-3"><a class="link-body-emphasis" href="mailto:ds4@the.al" target="_blank"><svg class="bi" width="24" height="24"><use xlink:href="#mail"/></svg></a></li>
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
"Done": "Fertig",
|
"Done": "Fertig",
|
||||||
"Hi, thank you for using this software.": "Hallo, vielen Dank, dass Sie diese Software verwenden.",
|
"Hi, thank you for using this software.": "Hallo, vielen Dank, dass Sie diese Software verwenden.",
|
||||||
"If you're finding it helpful and you want to support my efforts, feel free to": "Wenn Sie es hilfreich finden und meine Bemühungen unterstützen möchten, können Sie gerne",
|
"If you're finding it helpful and you want to support my efforts, feel free to": "Wenn Sie es hilfreich finden und meine Bemühungen unterstützen möchten, können Sie gerne",
|
||||||
"buy me a coffee": "mir einen Kaffee kaufen",
|
"buy me a coffee": "mir einen Kaffee anbieten",
|
||||||
"! :)": "! :)",
|
"! :)": "! :)",
|
||||||
"Do you have any suggestion or issue? Drop me a message via email or discord.": "Haben Sie einen Vorschlag oder ein Problem? Schicken Sie mir eine Nachricht per E-Mail oder Discord.",
|
"Do you have any suggestion or issue? Drop me a message via email or discord.": "Haben Sie einen Vorschlag oder ein Problem? Schicken Sie mir eine Nachricht per E-Mail oder Discord.",
|
||||||
"Cheers!": "Prost!",
|
"Cheers!": "Prost!",
|
||||||
@ -156,5 +156,9 @@
|
|||||||
"Translate this website in your language": "Übersetzen Sie diese Website in Ihre Sprache",
|
"Translate this website in your language": "Übersetzen Sie diese Website in Ihre Sprache",
|
||||||
", to help more people like you!": ", um mehr Menschen wie Sie zu helfen!",
|
", to help more people like you!": ", um mehr Menschen wie Sie zu helfen!",
|
||||||
|
|
||||||
|
"Board Model:": "",
|
||||||
|
"This feature is experimental.": "",
|
||||||
|
"Please let me know if the board model of your controller is not detected correctly.": "",
|
||||||
|
"Board model detection thanks to": "",
|
||||||
"": ""
|
"": ""
|
||||||
}
|
}
|
||||||
|
@ -155,5 +155,11 @@
|
|||||||
"Ship me a controller you would love to add (send me an email for organization).": "",
|
"Ship me a controller you would love to add (send me an email for organization).": "",
|
||||||
"Translate this website in your language": "",
|
"Translate this website in your language": "",
|
||||||
", to help more people like you!": "",
|
", to help more people like you!": "",
|
||||||
|
|
||||||
|
"Board Model:": "",
|
||||||
|
"This feature is experimental.": "",
|
||||||
|
"Please let me know if the board model of your controller is not detected correctly.": "",
|
||||||
|
"Board model detection thanks to": "",
|
||||||
|
|
||||||
"": ""
|
"": ""
|
||||||
}
|
}
|
||||||
|
@ -156,5 +156,10 @@
|
|||||||
"Translate this website in your language": "Traduci questo sito web nella tua lingua",
|
"Translate this website in your language": "Traduci questo sito web nella tua lingua",
|
||||||
", to help more people like you!": ", per aiutare più persone come te!",
|
", to help more people like you!": ", per aiutare più persone come te!",
|
||||||
|
|
||||||
|
"Board Model:": "Modello scheda:",
|
||||||
|
"This feature is experimental.": "Questa funzionalità è sperimentale.",
|
||||||
|
"Please let me know if the board model of your controller is not detected correctly.": "Scrivimi se il modello della scheda del tuo controller non viene riconosciuto correttamente.",
|
||||||
|
"Board model detection thanks to": "Rilevamento del modello della scheda grazie a",
|
||||||
|
|
||||||
"": ""
|
"": ""
|
||||||
}
|
}
|
||||||
|
@ -156,5 +156,10 @@
|
|||||||
"Translate this website in your language": "このウェブサイトをあなたの言語に翻訳する",
|
"Translate this website in your language": "このウェブサイトをあなたの言語に翻訳する",
|
||||||
", to help more people like you!": "、あなたのような多くの人々を助けるために!",
|
", to help more people like you!": "、あなたのような多くの人々を助けるために!",
|
||||||
|
|
||||||
|
"Board Model:": "",
|
||||||
|
"This feature is experimental.": "",
|
||||||
|
"Please let me know if the board model of your controller is not detected correctly.": "",
|
||||||
|
"Board model detection thanks to": "",
|
||||||
|
|
||||||
"": ""
|
"": ""
|
||||||
}
|
}
|
||||||
|
@ -155,5 +155,10 @@
|
|||||||
"Translate this website in your language": "Bu web sitesini kendi dilinize çevirin",
|
"Translate this website in your language": "Bu web sitesini kendi dilinize çevirin",
|
||||||
", to help more people like you!": ", sizin gibi daha fazla insanın faydalanması için!",
|
", to help more people like you!": ", sizin gibi daha fazla insanın faydalanması için!",
|
||||||
|
|
||||||
|
"Board Model:": "",
|
||||||
|
"This feature is experimental.": "",
|
||||||
|
"Please let me know if the board model of your controller is not detected correctly.": "",
|
||||||
|
"Board model detection thanks to": "",
|
||||||
|
|
||||||
"": ""
|
"": ""
|
||||||
}
|
}
|
||||||
|
@ -155,5 +155,11 @@
|
|||||||
"Ship me a controller you would love to add (send me an email for organization).": "给我寄送一个您想添加的手柄(发送电子邮件给我进行安排)。",
|
"Ship me a controller you would love to add (send me an email for organization).": "给我寄送一个您想添加的手柄(发送电子邮件给我进行安排)。",
|
||||||
"Translate this website in your language": "将这个网站翻译成您的语言",
|
"Translate this website in your language": "将这个网站翻译成您的语言",
|
||||||
", to help more people like you!": "以帮助更多像您一样的人!",
|
", to help more people like you!": "以帮助更多像您一样的人!",
|
||||||
|
|
||||||
|
"Board Model:": "",
|
||||||
|
"This feature is experimental.": "",
|
||||||
|
"Please let me know if the board model of your controller is not detected correctly.": "",
|
||||||
|
"Board model detection thanks to": "",
|
||||||
|
|
||||||
"": ""
|
"": ""
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user