chore: update html, js files
This commit is contained in:
parent
bfec6f9d69
commit
f129574b62
@ -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
|
||||
|
||||
@ -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
232
src/snek/static/nav-menu.js
Normal 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);
|
||||
@ -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>
|
||||
|
||||
Loadingโฆ
Reference in New Issue
Block a user