fix(applauncher): throttle inactivity timer resets in menus, optimize sound slider updates, and adjust keyboard layout/keys
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-01-06 - 3.34.2 - fix(applauncher)
|
||||
throttle inactivity timer resets in menus, optimize sound slider updates, and adjust keyboard layout/keys
|
||||
|
||||
- Add lastActivityTime and throttle resetInactivityTimer to only reset if 5+ seconds have passed in battery, sound, and wifi menus to reduce frequent resets from continuous input.
|
||||
- Remove @mousemove listener in menu containers and rely on mousedown + throttled resets to lower event noise.
|
||||
- Debounce slider mousemove handling in sound menu using requestAnimationFrame and pendingPercentage to batch setVolume calls and cancel RAF on mouseup, preventing excessive volume updates.
|
||||
- Add up/down arrow keys to virtual keyboard, reduce space key width from 4 to 3, and add .key.wide-3 CSS class to support the new sizing.
|
||||
|
||||
## 2026-01-06 - 3.34.1 - fix(elements/applauncher)
|
||||
add eco app launcher components, wifi/sound/battery menus, demos and new eco-screensaver; replace dees-screensaver (breaking API change)
|
||||
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@ecobridge.xyz/catalog',
|
||||
version: '3.34.1',
|
||||
version: '3.34.2',
|
||||
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
||||
}
|
||||
|
||||
@@ -248,6 +248,7 @@ export class EcoApplauncherBatterymenu extends DeesElement {
|
||||
private boundHandleClickOutside = this.handleClickOutside.bind(this);
|
||||
private inactivityTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
private readonly INACTIVITY_TIMEOUT = 60000; // 1 minute
|
||||
private lastActivityTime = 0;
|
||||
|
||||
public render(): TemplateResult {
|
||||
const fillClass = this.getFillClass();
|
||||
@@ -255,7 +256,6 @@ export class EcoApplauncherBatterymenu extends DeesElement {
|
||||
return html`
|
||||
<div class="menu-container"
|
||||
@click=${(e: MouseEvent) => e.stopPropagation()}
|
||||
@mousemove=${this.resetInactivityTimer}
|
||||
@mousedown=${this.resetInactivityTimer}
|
||||
>
|
||||
<div class="battery-display">
|
||||
@@ -340,6 +340,12 @@ export class EcoApplauncherBatterymenu extends DeesElement {
|
||||
}
|
||||
|
||||
private resetInactivityTimer(): void {
|
||||
const now = Date.now();
|
||||
// Throttle: only reset if 5+ seconds since last reset
|
||||
if (now - this.lastActivityTime < 5000) {
|
||||
return;
|
||||
}
|
||||
this.lastActivityTime = now;
|
||||
this.clearInactivityTimer();
|
||||
if (this.open) {
|
||||
this.inactivityTimeout = setTimeout(() => {
|
||||
|
||||
@@ -78,8 +78,10 @@ const qwertyLayout: IKeyConfig[][] = [
|
||||
[
|
||||
{ key: '123', display: '123', width: 1.5, type: 'layout', action: 'numbers' },
|
||||
{ key: 'globe', display: '🌐', type: 'special' },
|
||||
{ key: 'space', display: '', width: 4, type: 'space' },
|
||||
{ key: 'space', display: '', width: 3, type: 'space' },
|
||||
{ key: 'left', display: '←', type: 'special', action: 'arrow-left' },
|
||||
{ key: 'up', display: '↑', type: 'special', action: 'arrow-up' },
|
||||
{ key: 'down', display: '↓', type: 'special', action: 'arrow-down' },
|
||||
{ key: 'right', display: '→', type: 'special', action: 'arrow-right' },
|
||||
{ key: 'enter', display: '↵', width: 1.5, type: 'special' },
|
||||
],
|
||||
@@ -102,8 +104,10 @@ const numbersLayout: IKeyConfig[][] = [
|
||||
[
|
||||
{ key: 'ABC', display: 'ABC', width: 1.5, type: 'layout', action: 'qwerty' },
|
||||
{ key: 'globe', display: '🌐', type: 'special' },
|
||||
{ key: 'space', display: '', width: 4, type: 'space' },
|
||||
{ key: 'space', display: '', width: 3, type: 'space' },
|
||||
{ key: 'left', display: '←', type: 'special', action: 'arrow-left' },
|
||||
{ key: 'up', display: '↑', type: 'special', action: 'arrow-up' },
|
||||
{ key: 'down', display: '↓', type: 'special', action: 'arrow-down' },
|
||||
{ key: 'right', display: '→', type: 'special', action: 'arrow-right' },
|
||||
{ key: 'enter', display: '↵', width: 1.5, type: 'special' },
|
||||
],
|
||||
@@ -126,8 +130,10 @@ const symbolsLayout: IKeyConfig[][] = [
|
||||
[
|
||||
{ key: 'ABC', display: 'ABC', width: 1.5, type: 'layout', action: 'qwerty' },
|
||||
{ key: 'globe', display: '🌐', type: 'special' },
|
||||
{ key: 'space', display: '', width: 4, type: 'space' },
|
||||
{ key: 'space', display: '', width: 3, type: 'space' },
|
||||
{ key: 'left', display: '←', type: 'special', action: 'arrow-left' },
|
||||
{ key: 'up', display: '↑', type: 'special', action: 'arrow-up' },
|
||||
{ key: 'down', display: '↓', type: 'special', action: 'arrow-down' },
|
||||
{ key: 'right', display: '→', type: 'special', action: 'arrow-right' },
|
||||
{ key: 'enter', display: '↵', width: 1.5, type: 'special' },
|
||||
],
|
||||
@@ -245,6 +251,11 @@ export class EcoApplauncherKeyboard extends DeesElement {
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.key.wide-3 {
|
||||
flex: 3;
|
||||
max-width: 140px;
|
||||
}
|
||||
|
||||
.key.wide-4 {
|
||||
flex: 4;
|
||||
max-width: 180px;
|
||||
|
||||
@@ -249,6 +249,7 @@ export class EcoApplauncherSoundmenu extends DeesElement {
|
||||
private isDragging = false;
|
||||
private inactivityTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
private readonly INACTIVITY_TIMEOUT = 60000; // 1 minute
|
||||
private lastActivityTime = 0;
|
||||
|
||||
public render(): TemplateResult {
|
||||
const volumeIcon = this.getVolumeIcon();
|
||||
@@ -256,7 +257,6 @@ export class EcoApplauncherSoundmenu extends DeesElement {
|
||||
return html`
|
||||
<div class="menu-container"
|
||||
@click=${(e: MouseEvent) => e.stopPropagation()}
|
||||
@mousemove=${this.resetInactivityTimer}
|
||||
@mousedown=${this.resetInactivityTimer}
|
||||
>
|
||||
<div class="menu-header">
|
||||
@@ -368,16 +368,34 @@ export class EcoApplauncherSoundmenu extends DeesElement {
|
||||
private handleSliderMouseDown(e: MouseEvent): void {
|
||||
this.isDragging = true;
|
||||
const slider = e.currentTarget as HTMLElement;
|
||||
let rafId: number | null = null;
|
||||
let pendingPercentage: number | null = null;
|
||||
|
||||
const updateVolume = () => {
|
||||
if (pendingPercentage !== null) {
|
||||
this.setVolume(pendingPercentage);
|
||||
pendingPercentage = null;
|
||||
}
|
||||
rafId = null;
|
||||
};
|
||||
|
||||
const handleMouseMove = (moveEvent: MouseEvent) => {
|
||||
if (!this.isDragging) return;
|
||||
const rect = slider.getBoundingClientRect();
|
||||
const percentage = Math.round(((moveEvent.clientX - rect.left) / rect.width) * 100);
|
||||
this.setVolume(Math.max(0, Math.min(100, percentage)));
|
||||
pendingPercentage = Math.max(0, Math.min(100, Math.round(((moveEvent.clientX - rect.left) / rect.width) * 100)));
|
||||
if (!rafId) {
|
||||
rafId = requestAnimationFrame(updateVolume);
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseUp = () => {
|
||||
this.isDragging = false;
|
||||
if (rafId) {
|
||||
cancelAnimationFrame(rafId);
|
||||
}
|
||||
if (pendingPercentage !== null) {
|
||||
this.setVolume(pendingPercentage);
|
||||
}
|
||||
document.removeEventListener('mousemove', handleMouseMove);
|
||||
document.removeEventListener('mouseup', handleMouseUp);
|
||||
};
|
||||
@@ -421,6 +439,12 @@ export class EcoApplauncherSoundmenu extends DeesElement {
|
||||
}
|
||||
|
||||
private resetInactivityTimer(): void {
|
||||
const now = Date.now();
|
||||
// Throttle: only reset if 5+ seconds since last reset
|
||||
if (now - this.lastActivityTime < 5000) {
|
||||
return;
|
||||
}
|
||||
this.lastActivityTime = now;
|
||||
this.clearInactivityTimer();
|
||||
if (this.open) {
|
||||
this.inactivityTimeout = setTimeout(() => {
|
||||
|
||||
@@ -231,12 +231,12 @@ export class EcoApplauncherWifimenu extends DeesElement {
|
||||
private boundHandleClickOutside = this.handleClickOutside.bind(this);
|
||||
private inactivityTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
private readonly INACTIVITY_TIMEOUT = 60000; // 1 minute
|
||||
private lastActivityTime = 0;
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
<div class="menu-container"
|
||||
@click=${(e: MouseEvent) => e.stopPropagation()}
|
||||
@mousemove=${this.resetInactivityTimer}
|
||||
@mousedown=${this.resetInactivityTimer}
|
||||
>
|
||||
<div class="menu-header">
|
||||
@@ -348,6 +348,12 @@ export class EcoApplauncherWifimenu extends DeesElement {
|
||||
}
|
||||
|
||||
private resetInactivityTimer(): void {
|
||||
const now = Date.now();
|
||||
// Throttle: only reset if 5+ seconds since last reset
|
||||
if (now - this.lastActivityTime < 5000) {
|
||||
return;
|
||||
}
|
||||
this.lastActivityTime = now;
|
||||
this.clearInactivityTimer();
|
||||
if (this.open) {
|
||||
this.inactivityTimeout = setTimeout(() => {
|
||||
|
||||
Reference in New Issue
Block a user