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);