class CustomLockscreen extends HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open' }); this.shadowRoot.innerHTML = `
00:00
Loading...
${Array.from({ length: 9 }, (_, i) => `
`).join('')}

Draw your pattern to unlock

`; this.initTime(); this.initPatternLock(); } initTime() { const timeElement = this.shadowRoot.querySelector('.time-display'); const dateElement = this.shadowRoot.querySelector('.date-display'); const updateTime = () => { const now = new Date(); const timeString = now.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit' }); const dateString = now.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); timeElement.textContent = timeString; dateElement.textContent = dateString; }; updateTime(); setInterval(updateTime, 1000); } initPatternLock() { const dots = this.shadowRoot.querySelectorAll('.pattern-dot'); let selectedDots = []; const correctPattern = [0, 3, 6, 7, 8]; dots.forEach((dot, index) => { dot.addEventListener('click', () => { if (!selectedDots.includes(index)) { selectedDots.push(index); dot.classList.add('selected'); // Draw lines between selected dots if (selectedDots.length > 1) { const prevIndex = selectedDots[selectedDots.length - 2]; const prevDot = dots[prevIndex]; const line = document.createElement('div'); line.className = 'pattern-line'; // Calculate line position and dimensions const rect1 = prevDot.getBoundingClientRect(); const rect2 = dot.getBoundingClientRect(); const x1 = rect1.left + rect1.width / 2; const y1 = rect1.top + rect1.height / 2; const x2 = rect2.left + rect2.width / 2; const y2 = rect2.top + rect2.height / 2; const length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2); const angle = Math.atan2(y2 - y1, x2 - x1); line.style.width = `${length}px`; line.style.transform = `rotate(${angle}rad)'; line.style.left = `${x1}px`; line.style.top = `${y1}px'; this.shadowRoot.querySelector('.pattern-grid').appendChild(line); } // Check if pattern is complete if (selectedDots.length === correctPattern.length) { if (JSON.stringify(selectedDots) === JSON.stringify(correctPattern)) { this.toggleLock(); } else { // Wrong pattern - reset setTimeout(() => { this.resetPattern(); }, 500); } } }); }); // Reset pattern on mouse up (for mobile) document.addEventListener('mouseup', () => this.resetPattern()); document.addEventListener('touchend', () => this.resetPattern()); } resetPattern() { const dots = this.shadowRoot.querySelectorAll('.pattern-dot'); const lines = this.shadowRoot.querySelectorAll('.pattern-line'); lines.forEach(line => line.remove()); dots.forEach(dot => dot.classList.remove('selected')); selectedDots = []; } toggleLock() { if (this.style.display === 'none') { this.style.display = 'flex'; document.body.style.overflow = 'hidden'; } else { this.style.display = 'none'; document.body.style.overflow = ''; // Remove all pattern lines this.shadowRoot.querySelectorAll('.pattern-line').forEach(line => line.remove()); selectedDots = []; } } } customElements.define('custom-lockscreen', CustomLockscreen);