183 lines
No EOL
6.6 KiB
JavaScript
183 lines
No EOL
6.6 KiB
JavaScript
nr.defineComponent({
|
|
name: "login",
|
|
template: `
|
|
<div style="height: 100vh; width: 100vw;" class="d-flex justify-content-center align-items-center">
|
|
<div id="login" class="card" style="max-width: 30rem; flex: 1 1 auto;">
|
|
<div class="header w-100 d-flex justify-content-center">
|
|
<img src="/favicon.png" style="width: 3rem;">
|
|
</div>
|
|
<div class="header">Welcome to <code>callback</code>.</div>
|
|
<div class="body">
|
|
<div class="fill-error alert m-0 m-top-2" style="display: none;">
|
|
error
|
|
</div>
|
|
<div class="textfield m-0 m-bottom-2 m-top-2">
|
|
<span class="label">Username</span>
|
|
<input type="text" placeholder="">
|
|
</div>
|
|
<div class="fill-primary linear-progress indeterminate m-bottom-2" style="display: none;"><div></div></div>
|
|
<button class="small w-100 fill-primary btn" type="submit">Login</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`,
|
|
beforeCreate: () => {
|
|
return { useShadowRoot: false }
|
|
},
|
|
afterCreate: (shadowRoot, config = {}, env) => {
|
|
const compName = nr.components[nr.mountedComponents[env.mountingTo]].name;
|
|
const ctx = nr.findComponentById(env.cid);
|
|
const form = {
|
|
loginButton: ctx.querySelector('button'),
|
|
progressBar: ctx.querySelector('.linear-progress'),
|
|
usernameField: ctx.querySelector('.textfield input'),
|
|
errorContainer: ctx.querySelector('.alert')
|
|
}
|
|
|
|
if (localStorage.getItem('username')) {
|
|
form.usernameField.value = localStorage.getItem('username');
|
|
handleLogin();
|
|
}
|
|
|
|
form.loginButton.addEventListener('click', handleLogin);
|
|
|
|
function showError(error) {
|
|
form.progressBar.style.display = 'none';
|
|
form.loginButton.disabled = false;
|
|
form.usernameField.disabled = false;
|
|
form.errorContainer.style.display = 'block';
|
|
form.errorContainer.textContent = error;
|
|
form.usernameField.focus();
|
|
}
|
|
|
|
function handleLogin() {
|
|
try {
|
|
form.errorContainer.style.display = 'none';
|
|
form.progressBar.style.display = 'block';
|
|
form.loginButton.disabled = true;
|
|
form.usernameField.disabled = true;
|
|
const username = form.usernameField.value;
|
|
|
|
if (!username) throw new Error('Username cannot be empty');
|
|
console.log(`[${compName}] Trying to connect as ${username}`);
|
|
let protocol
|
|
switch (window.location.protocol) {
|
|
case 'http:':
|
|
protocol = 'ws:';
|
|
break;
|
|
case 'https:':
|
|
protocol = 'wss:';
|
|
break;
|
|
default:
|
|
throw new Error('Unknown page protocol');
|
|
}
|
|
window.callback = {
|
|
socket: new WebSocket(`${protocol}//${window.location.host}?u=${encodeURIComponent(username)}`)
|
|
}
|
|
|
|
function handleWSLogin(message) {
|
|
try {
|
|
const res = JSON.parse(message.data);
|
|
if (res.error) throw new Error(res.message);
|
|
localStorage.setItem('username', username);
|
|
console.log(`[${compName}] Logged in as ${username}`)
|
|
nr.unmount(env.mountingTo);
|
|
nr.mount(config?.appComponent || 'callback', env.mountingTo)
|
|
} catch (e) {
|
|
showError(e.message);
|
|
console.error(e);
|
|
}
|
|
}
|
|
|
|
window.callback.socket.addEventListener('open', console.log(`[${compName}] Connected to websocket`));
|
|
window.callback.socket.addEventListener('message', handleWSLogin);
|
|
} catch (e) {
|
|
showError(e.message);
|
|
console.error(e);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
nr.defineComponent({
|
|
name: 'callback',
|
|
template: `
|
|
<div class="d-flex">
|
|
<div class="d-flex" style="height: 100vh; width: 100vw; position: fixed; left: -100%; transition: left 0.25s ease-out; z-index: 1000" id="sidebar">
|
|
<div class="navdrawer modal" id="sidebarbody">
|
|
<div style="all: unset;">
|
|
<div class="d-flex w-100 justify-content-space-between align-items-center">
|
|
<img src="/favicon.png" style="width: 1.5rem" alt="Logo" class="m-right-3">
|
|
<div class="w-100 d-flex align-items-center">
|
|
<span class="text-bold" style="margin-right: auto;">Chats</span>
|
|
<button class="small fill-primary btn w-50">New</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="chats">
|
|
<div class="active">
|
|
<span class="label">Label</span>
|
|
</div>
|
|
<div>
|
|
<span class="label">Label</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex flex-column w-100" style="height: 100vh;">
|
|
<div style="background-color: var(--md-sys-color-surface-container)" class="d-flex align-items-center w-100 p-3 gap-3">
|
|
<span class="material-symbols-outlined" id="menutoggle">menu</span>
|
|
<span>Person</span>
|
|
</div>
|
|
<div style="height: 100%;">
|
|
CHATDIV
|
|
</div>
|
|
<div style="background-color: var(--md-sys-color-surface-container)" class="d-flex align-items-center w-100">
|
|
<div class="textfield m-0 w-100 m-left-3">
|
|
<span class="label">Message</span>
|
|
<input type="text" placeholder="">
|
|
</div>
|
|
<button type="submit" class="material-symbols-outlined fill-primary btn m-right-3" disabled>send</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`,
|
|
beforeCreate: () => {
|
|
return { useShadowRoot: false }
|
|
},
|
|
afterCreate: () => {
|
|
const sidebar = document.querySelector('#sidebar');
|
|
const sidebarBody = document.querySelector('#sidebarbody');
|
|
const menutoggle = document.querySelector('#menutoggle');
|
|
menutoggle.addEventListener('click', () => {
|
|
sidebar.style.left = "0";
|
|
});
|
|
sidebar.addEventListener('click', (event) => {
|
|
if (!sidebarBody.contains(event.target)) {
|
|
sidebar.style.left = "-100%";
|
|
}
|
|
});
|
|
|
|
const resizeObserver = new ResizeObserver(entries => {
|
|
for (let entry of entries) {
|
|
const rootFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
const fortyRemInPixels = 65 * rootFontSize;
|
|
|
|
if (entry.contentRect.width > fortyRemInPixels) {
|
|
sidebar.style.position = 'static';
|
|
sidebarBody.classList.remove('modal');
|
|
sidebarBody.classList.add('standart');
|
|
menutoggle.style.display = 'none';
|
|
} else {
|
|
sidebar.style.position = 'fixed';
|
|
sidebarBody.classList.remove('standart');
|
|
sidebarBody.classList.add('modal');
|
|
menutoggle.style.display = 'block';
|
|
}
|
|
}
|
|
});
|
|
|
|
resizeObserver.observe(document.body);
|
|
}
|
|
}) |