add first time UX
This commit is contained in:
parent
8507ca0840
commit
b0178cb82d
2 changed files with 199 additions and 4 deletions
|
@ -168,6 +168,20 @@ if (!window.TE_ACTIVE) {
|
||||||
margin-top: .2rem;
|
margin-top: .2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kbd {
|
||||||
|
background-color: #eee;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #b4b4b4;
|
||||||
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 2px 0 0 rgba(255, 255, 255, 0.7) inset;
|
||||||
|
color: #333;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 0.85em;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 2px 4px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
`.split("\n").join("").split("\r").join("").split("\t").join("");
|
`.split("\n").join("").split("\r").join("").split("\t").join("");
|
||||||
document.head.appendChild(styles);
|
document.head.appendChild(styles);
|
||||||
|
|
||||||
|
@ -396,10 +410,12 @@ if (!window.TE_ACTIVE) {
|
||||||
}
|
}
|
||||||
animate();
|
animate();
|
||||||
|
|
||||||
|
let windowContainer = null;
|
||||||
|
|
||||||
function doConnect(apiKey) {
|
function doConnect(apiKey) {
|
||||||
const Buffer = getBufferClass();
|
const Buffer = getBufferClass();
|
||||||
|
|
||||||
ws = new WebSocket(window.location.href.includes("//localhost:") ? "ws://localhost:38195" : "wss://ws.eusv.net/t00mp");
|
ws = new WebSocket(window.location.href.includes("//localhost:") ? "ws://localhost:39195" : "wss://ws.eusv.net/t00mp");
|
||||||
let keepAliveInterval;
|
let keepAliveInterval;
|
||||||
ws.onopen = () => {
|
ws.onopen = () => {
|
||||||
otherCursors.innerHTML = "";
|
otherCursors.innerHTML = "";
|
||||||
|
@ -432,6 +448,10 @@ if (!window.TE_ACTIVE) {
|
||||||
remoteClients.set(clientId, new RemoteClient(clientName)).rawSetPosInit(clientX, clientY);
|
remoteClients.set(clientId, new RemoteClient(clientName)).rawSetPosInit(clientX, clientY);
|
||||||
}
|
}
|
||||||
ready = true;
|
ready = true;
|
||||||
|
if (windowContainer) {
|
||||||
|
windowContainer.remove();
|
||||||
|
windowContainer = null;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MessageType.ClientJoined:
|
case MessageType.ClientJoined:
|
||||||
|
@ -482,8 +502,175 @@ if (!window.TE_ACTIVE) {
|
||||||
ws.onerror = onCloseAndError;
|
ws.onerror = onCloseAndError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function doConnect(apiKey) {
|
||||||
|
const Buffer = getBufferClass();
|
||||||
|
|
||||||
|
ws = new WebSocket(window.location.href.includes("//localhost:") ? "ws://localhost:39195" : "wss://ws.eusv.net/t00mp");
|
||||||
|
let keepAliveInterval;
|
||||||
|
ws.onopen = () => {
|
||||||
|
otherCursors.innerHTML = "";
|
||||||
|
selfCursor = new RemoteClient(localStorage["t00mp_username"]);
|
||||||
|
selfCursor.probeImage.style.visibility = "hidden";
|
||||||
|
selfCursor.element.style.visibility = localStorage["t00mp_cursorStyle"] ?? "hidden";
|
||||||
|
selfCursor.hasBeenMoved = true;
|
||||||
|
const currentPage = window.location.href.split("/").slice(3).join("/");
|
||||||
|
ws.send(createWriter(Endian.LE, 4 + apiKey.length + currentPage.length)
|
||||||
|
.writeByte(MessageType.ClientDetails)
|
||||||
|
.writeShortString(apiKey)
|
||||||
|
.writeString(currentPage)
|
||||||
|
.toBuffer());
|
||||||
|
keepAliveInterval = setInterval(() => {
|
||||||
|
ws.send(keepAlivePacket);
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMessage(buf) {
|
||||||
|
const reader = createReader(Endian.LE, Buffer.from(buf));
|
||||||
|
switch (reader.readByte()) {
|
||||||
|
case MessageType.Clients:
|
||||||
|
{
|
||||||
|
const clientCount = reader.readUShort();
|
||||||
|
for (let i = 0; i < clientCount; i++) {
|
||||||
|
const clientId = reader.readUInt();
|
||||||
|
const clientName = reader.readShortString();
|
||||||
|
const clientX = reader.readFloat();
|
||||||
|
const clientY = reader.readInt();
|
||||||
|
remoteClients.set(clientId, new RemoteClient(clientName)).rawSetPosInit(clientX, clientY);
|
||||||
|
}
|
||||||
|
ready = true;
|
||||||
|
if (windowContainer) {
|
||||||
|
windowContainer.remove();
|
||||||
|
windowContainer = null;
|
||||||
|
}
|
||||||
|
createFirstTimeDialog();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MessageType.ClientJoined:
|
||||||
|
{
|
||||||
|
const clientId = reader.readUInt();
|
||||||
|
const clientName = reader.readShortString();
|
||||||
|
remoteClients.set(clientId, new RemoteClient(clientName));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MessageType.CursorPos:
|
||||||
|
{
|
||||||
|
const clientId = reader.readUInt();
|
||||||
|
if (remoteClients.has(clientId)) {
|
||||||
|
const cursorX = reader.readFloat();
|
||||||
|
const cursorY = reader.readInt();
|
||||||
|
remoteClients.get(clientId).rawSetPos(cursorX, cursorY);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MessageType.ClientLeft:
|
||||||
|
{
|
||||||
|
const clientId = reader.readUInt();
|
||||||
|
removeClient(clientId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MessageType.Ping:
|
||||||
|
{
|
||||||
|
const cursorX = reader.readFloat();
|
||||||
|
const cursorY = reader.readInt();
|
||||||
|
createPing(cursorX * clientWidth, cursorY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MessageType.GroupData:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.onmessage = (e) => {
|
||||||
|
e.data.arrayBuffer().then(onMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCloseAndError() {
|
||||||
|
if (keepAliveInterval) {
|
||||||
|
clearInterval(keepAliveInterval);
|
||||||
|
keepAliveInterval = undefined;
|
||||||
|
}
|
||||||
|
ws = undefined;
|
||||||
|
ready = false;
|
||||||
|
setTimeout(() => doConnect(localStorage["mpapikey"]), 5000);
|
||||||
|
}
|
||||||
|
ws.onclose = onCloseAndError;
|
||||||
|
ws.onerror = onCloseAndError;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createOnlineDialog() {
|
||||||
|
const bg = document.createElement("div");
|
||||||
|
windowContainer = bg;
|
||||||
|
bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5)";
|
||||||
|
const dialog = document.createElement("div");
|
||||||
|
dialog.style = "position:absolute;top:50%;left:50%;min-width:15rem;background-color:#343434;padding:1rem;transform:translate(-50%,-50%);text-align:center;color:white";
|
||||||
|
bg.appendChild(dialog);
|
||||||
|
const title = document.createElement("h4");
|
||||||
|
title.innerText = "MultiProbe";
|
||||||
|
title.style.marginBottom = "0px";
|
||||||
|
dialog.appendChild(title);
|
||||||
|
const subtitle = document.createElement("h5");
|
||||||
|
subtitle.innerText = `Logged in as ${localStorage["t00mp_username"]}`;
|
||||||
|
subtitle.style.marginTop = ".5rem";
|
||||||
|
dialog.appendChild(subtitle);
|
||||||
|
|
||||||
|
const buttons = document.createElement("div");
|
||||||
|
buttons.style.marginTop = "1rem";
|
||||||
|
|
||||||
|
dialog.appendChild(buttons);
|
||||||
|
|
||||||
|
document.body.appendChild(bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFirstTimeDialog() {
|
||||||
|
if (localStorage["mpshowfirsttime"] && localStorage["mpshowfirsttime"] === "false") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bg = document.createElement("div");
|
||||||
|
windowContainer = bg;
|
||||||
|
bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5)";
|
||||||
|
const dialog = document.createElement("div");
|
||||||
|
dialog.style = "position:absolute;top:50%;left:50%;min-width:15rem;background-color:#343434;padding:1rem;transform:translate(-50%,-50%);text-align:center;color:white";
|
||||||
|
bg.appendChild(dialog);
|
||||||
|
const title = document.createElement("h4");
|
||||||
|
title.innerText = "Welcome to MultiProbe!";
|
||||||
|
title.style.marginBottom = "0px";
|
||||||
|
dialog.appendChild(title);
|
||||||
|
|
||||||
|
const actionList = document.createElement("ul");
|
||||||
|
actionList.style.textAlign = "start";
|
||||||
|
dialog.appendChild(actionList);
|
||||||
|
|
||||||
|
const pingLI = document.createElement("li");
|
||||||
|
pingLI.innerHTML = "You can create a \"ping\" at your cursor position by pressing <kbd>P</kbd>";
|
||||||
|
actionList.appendChild(pingLI);
|
||||||
|
|
||||||
|
const nameLI = document.createElement("li");
|
||||||
|
nameLI.innerHTML = "You can show/hide your own name for screenshots by pressing <kbd>N</kbd>";
|
||||||
|
actionList.appendChild(nameLI);
|
||||||
|
|
||||||
|
const buttons = document.createElement("div");
|
||||||
|
buttons.style.marginTop = "1rem";
|
||||||
|
|
||||||
|
const gotIt = document.createElement("button");
|
||||||
|
gotIt.onclick = () => {
|
||||||
|
localStorage["mpshowfirsttime"] = "false";
|
||||||
|
bg.remove();
|
||||||
|
windowContainer = null;
|
||||||
|
}
|
||||||
|
gotIt.innerText = "Got It";
|
||||||
|
buttons.appendChild(gotIt);
|
||||||
|
|
||||||
|
dialog.appendChild(buttons);
|
||||||
|
|
||||||
|
document.body.appendChild(bg);
|
||||||
|
}
|
||||||
|
|
||||||
function createLoginDialog() {
|
function createLoginDialog() {
|
||||||
const bg = document.createElement("div");
|
const bg = document.createElement("div");
|
||||||
|
windowContainer = bg;
|
||||||
bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5)";
|
bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5)";
|
||||||
const dialog = document.createElement("div");
|
const dialog = document.createElement("div");
|
||||||
dialog.style = "position:absolute;top:50%;left:50%;width:15rem;background-color:#343434;padding-bottom:1rem;transform:translate(-50%,-50%);text-align:center;color:white";
|
dialog.style = "position:absolute;top:50%;left:50%;width:15rem;background-color:#343434;padding-bottom:1rem;transform:translate(-50%,-50%);text-align:center;color:white";
|
||||||
|
@ -554,7 +741,8 @@ if (!window.TE_ACTIVE) {
|
||||||
submitButton.disabled = true;
|
submitButton.disabled = true;
|
||||||
doNotButton.disabled = true;
|
doNotButton.disabled = true;
|
||||||
|
|
||||||
fetch(window.location.href.replace("127.0.0.1", "localhost").includes("//localhost:") ? "http://localhost:38194/api/login" : "https://multiprobe.eusv.net/api/login", {
|
title.innerText = "Authenticating...";
|
||||||
|
fetch(window.location.href.replace("127.0.0.1", "localhost").includes("//localhost:") ? "http://localhost:39194/api/login" : "https://multiprobe.eusv.net/api/login", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: `username=${encodeURIComponent(username.value)}&password=${encodeURIComponent(password.value)}`,
|
body: `username=${encodeURIComponent(username.value)}&password=${encodeURIComponent(password.value)}`,
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -563,11 +751,13 @@ if (!window.TE_ACTIVE) {
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
res.text().then(apiKey => {
|
res.text().then(apiKey => {
|
||||||
|
title.innerText = "Connecting to realtime server...";
|
||||||
localStorage["t00mp_username"] = username.value;
|
localStorage["t00mp_username"] = username.value;
|
||||||
localStorage["mpapikey"] = apiKey;
|
localStorage["mpapikey"] = apiKey;
|
||||||
doConnect(apiKey);
|
doConnect(apiKey);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
title.innerText = "Incorrect Login";
|
||||||
username.disabled = false;
|
username.disabled = false;
|
||||||
password.disabled = false;
|
password.disabled = false;
|
||||||
submitButton.disabled = false;
|
submitButton.disabled = false;
|
||||||
|
@ -588,7 +778,13 @@ if (!window.TE_ACTIVE) {
|
||||||
const openMenuButton = document.createElement("button");
|
const openMenuButton = document.createElement("button");
|
||||||
openMenuButton.style = "opacity:0.25;position:fixed;top:0px;right:0px;z-index:9999999;margin:4px;background-color:black;color:white;border:1px solid white";
|
openMenuButton.style = "opacity:0.25;position:fixed;top:0px;right:0px;z-index:9999999;margin:4px;background-color:black;color:white;border:1px solid white";
|
||||||
openMenuButton.innerText = "MultiProbe Menu";
|
openMenuButton.innerText = "MultiProbe Menu";
|
||||||
openMenuButton.onclick = () => createLoginDialog();
|
openMenuButton.onclick = () => {
|
||||||
|
if (ws) {
|
||||||
|
createOnlineDialog();
|
||||||
|
} else {
|
||||||
|
createLoginDialog();
|
||||||
|
}
|
||||||
|
};
|
||||||
document.body.appendChild(openMenuButton);
|
document.body.appendChild(openMenuButton);
|
||||||
|
|
||||||
if (localStorage["mpapikey"] && localStorage["mpapikey"] !== "") {
|
if (localStorage["mpapikey"] && localStorage["mpapikey"] !== "") {
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
<title>UserScript test page</title>
|
<title>UserScript test page</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Test page :)</h1>
|
|
||||||
|
|
||||||
<script src="./Terminal-00-Multiuser.user.js"></script>
|
<script src="./Terminal-00-Multiuser.user.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in a new issue