chore: update html, js files

This commit is contained in:
retoor 2026-01-03 14:13:55 +01:00
parent bfec6f9d69
commit f129574b62
4 changed files with 256 additions and 25 deletions

View File

@ -18,6 +18,14 @@
## Version 1.18.0 - 2026-01-03
update html, js files
**Changes:** 2 files, 271 lines
**Languages:** HTML (39 lines), JavaScript (232 lines)
## Version 1.17.0 - 2026-01-03
update css, js, py files

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "Snek"
version = "1.17.0"
version = "1.18.0"
readme = "README.md"
#license = { file = "LICENSE", content-type="text/markdown" }
description = "Snek Chat Application by Molodetz"

232
src/snek/static/nav-menu.js Normal file
View File

@ -0,0 +1,232 @@
// retoor <retoor@molodetz.nl>
class NavMenu extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this._isOpen = false;
this._boundClickOutside = this._handleClickOutside.bind(this);
const style = document.createElement('style');
style.textContent = `
:host {
display: inline-block;
position: relative;
}
.nav-container {
position: relative;
}
.menu-toggle {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 4px;
width: 32px;
height: 32px;
padding: 6px;
background: none;
border: none;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
}
.menu-toggle .bar {
width: 18px;
height: 2px;
background-color: #888;
border-radius: 1px;
transition: all 0.2s ease;
}
.menu-toggle:hover .bar {
background-color: #fff;
}
.menu-toggle:hover {
background-color: rgba(255, 255, 255, 0.05);
}
:host([open]) .menu-toggle {
background-color: rgba(255, 255, 255, 0.05);
}
:host([open]) .menu-toggle .bar {
background-color: #fff;
}
:host([open]) .menu-toggle .bar:nth-child(1) {
transform: rotate(45deg) translate(4px, 4px);
}
:host([open]) .menu-toggle .bar:nth-child(2) {
opacity: 0;
}
:host([open]) .menu-toggle .bar:nth-child(3) {
transform: rotate(-45deg) translate(4px, -4px);
}
.menu-panel {
position: absolute;
top: 100%;
right: 0;
margin-top: 8px;
background-color: #111;
border: 1px solid #333;
border-radius: 8px;
padding: 8px 0;
display: none;
flex-direction: column;
min-width: 180px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
z-index: 1000;
}
:host([open]) .menu-panel {
display: flex;
}
.menu-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 16px;
color: #888;
text-decoration: none;
font-size: 0.95em;
transition: all 0.2s ease;
cursor: pointer;
border: none;
background: none;
width: 100%;
text-align: left;
}
.menu-item:hover {
color: #fff;
background-color: rgba(255, 255, 255, 0.05);
}
.menu-item .icon {
font-size: 1.1em;
}
.menu-item.hidden {
display: none;
}
`;
const container = document.createElement('div');
container.className = 'nav-container';
this._menuPanel = document.createElement('div');
this._menuPanel.className = 'menu-panel';
this._toggleButton = document.createElement('button');
this._toggleButton.className = 'menu-toggle';
this._toggleButton.setAttribute('aria-label', 'Toggle navigation menu');
this._toggleButton.innerHTML = '<span class="bar"></span><span class="bar"></span><span class="bar"></span>';
this._toggleButton.addEventListener('click', (e) => {
e.stopPropagation();
this._toggle();
});
this._createMenuItems();
container.appendChild(this._menuPanel);
container.appendChild(this._toggleButton);
this.shadowRoot.append(style, container);
}
_createMenuItems() {
const items = [
{ icon: '๐Ÿ ', label: 'Home', href: '/web.html' },
{ icon: '๐Ÿ“‚', label: 'Files', href: '/drive.html' },
{ icon: '๐Ÿ”', label: 'Search', href: '/search-user.html' },
{ icon: '๐Ÿ“ฅ', label: 'Install', href: '#', id: 'install-button', hidden: true },
{ icon: '๐Ÿ’ฌ', label: 'Forum', href: '/forum/index.html' },
{ icon: 'โš™๏ธ', label: 'Settings', href: '/settings/index.html' },
{ icon: 'โœ‰๏ธ', label: 'Notifications', href: '#', action: 'notifications' },
{ icon: '๐Ÿ”’', label: 'Logout', href: '/logout.html' }
];
items.forEach(item => {
const link = document.createElement('a');
link.className = 'menu-item';
if (item.hidden) {
link.classList.add('hidden');
}
link.href = item.href;
if (item.id) {
link.id = item.id;
this['_' + item.id.replace('-', '')] = link;
}
if (item.action === 'notifications') {
link.addEventListener('click', (e) => {
e.preventDefault();
this._close();
if (typeof window.registerNotificationsServiceWorker === 'function') {
window.registerNotificationsServiceWorker();
}
});
} else if (item.href !== '#') {
link.addEventListener('click', () => {
this._close();
});
}
link.innerHTML = `<span class="icon">${item.icon}</span><span>${item.label}</span>`;
this._menuPanel.appendChild(link);
});
}
_toggle() {
if (this._isOpen) {
this._close();
} else {
this._open();
}
}
_open() {
this._isOpen = true;
this.setAttribute('open', '');
setTimeout(() => {
document.addEventListener('click', this._boundClickOutside);
}, 0);
}
_close() {
this._isOpen = false;
this.removeAttribute('open');
document.removeEventListener('click', this._boundClickOutside);
}
_handleClickOutside(event) {
const path = event.composedPath();
if (!path.includes(this)) {
this._close();
}
}
showInstallButton() {
const installBtn = this.shadowRoot.getElementById('install-button');
if (installBtn) {
installBtn.classList.remove('hidden');
}
}
getInstallButton() {
return this.shadowRoot.getElementById('install-button');
}
disconnectedCallback() {
document.removeEventListener('click', this._boundClickOutside);
}
}
customElements.define('nav-menu', NavMenu);

View File

@ -13,6 +13,7 @@
<script src="/file-upload-grid.js" type="module"></script>
<script src="/polyfills/Promise.withResolvers.js" type="module"></script>
<script src="/nav-menu.js" type="module"></script>
<script src="/push.js" type="module"></script>
<script src="/fancy-button.js" type="module"></script>
<script src="/upload-button.js" type="module"></script>
@ -40,17 +41,7 @@
<body>
<header>
<div class="logo no-select">{% block header_text %}{% endblock %}</div>
<nav class="no-select" style="overflow:hidden;scroll-behavior:smooth">
<a class="no-select" href="/web.html">๐Ÿ </a>
<a class="no-select" href="/drive.html">๐Ÿ“‚</a>
<a class="no-select" href="/search-user.html">๐Ÿ”</a>
<a class="no-select" style="display:none" id="install-button" href="#">๐Ÿ“ฅ</a>
<a class="no-select" href="/forum/index.html">๐Ÿ’ฌ</a>
<a class="no-select" href="/settings/index.html">โš™๏ธ</a>
<a class="no-select" href="#" onclick="registerNotificationsServiceWorker()">โœ‰๏ธ</a>
<a class="no-select" href="/logout.html">๐Ÿ”’</a>
</nav>
<nav-menu></nav-menu>
</header>
{% block sidebar %}
@ -154,19 +145,19 @@ app.starField.renderWord("H4x0r 1337")
let installPrompt = null
window.addEventListener("beforeinstallprompt", (e) => {
//e.preventDefault();
installPrompt = e;
//document.addEventListener("DOMContentLoaded", () => {
const button = document.getElementById("install-button")
button.style.display = 'inline-block'
button.addEventListener("click", async ()=>{
const result = await installPrompt.prompt()
})
})
const navMenu = document.querySelector('nav-menu');
if (navMenu) {
navMenu.showInstallButton();
const button = navMenu.getInstallButton();
if (button) {
button.addEventListener("click", async (evt) => {
evt.preventDefault();
const result = await installPrompt.prompt();
});
}
}
})
;
</script>