vibetunnel/web/src/client/components/header-base.ts
Helmut Januschka f3b2022d48
Integrate screencap functionality for remote screen sharing (#209)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2025-07-06 03:31:34 +01:00

117 lines
3.4 KiB
TypeScript

/**
* Base functionality for header components
*/
import { LitElement } from 'lit';
import { property, state } from 'lit/decorators.js';
import { TIMING } from '../utils/constants.js';
import type { Session } from './session-list.js';
export abstract class HeaderBase extends LitElement {
createRenderRoot() {
return this;
}
@property({ type: Array }) sessions: Session[] = [];
@property({ type: Boolean }) hideExited = true;
@property({ type: String }) currentUser: string | null = null;
@property({ type: String }) authMethod: string | null = null;
@state() protected killingAll = false;
@state() protected showUserMenu = false;
protected get runningSessions(): Session[] {
return this.sessions.filter((session) => session.status === 'running');
}
protected get exitedSessions(): Session[] {
return this.sessions.filter((session) => session.status === 'exited');
}
protected handleCreateSession(e: MouseEvent) {
// Capture button position for view transition
const button = e.currentTarget as HTMLButtonElement;
const rect = button.getBoundingClientRect();
// Store position in CSS custom properties for the transition
document.documentElement.style.setProperty('--vt-button-x', `${rect.left + rect.width / 2}px`);
document.documentElement.style.setProperty('--vt-button-y', `${rect.top + rect.height / 2}px`);
document.documentElement.style.setProperty('--vt-button-width', `${rect.width}px`);
document.documentElement.style.setProperty('--vt-button-height', `${rect.height}px`);
this.dispatchEvent(new CustomEvent('create-session'));
}
protected handleKillAll() {
if (this.killingAll) return;
this.killingAll = true;
this.requestUpdate();
this.dispatchEvent(new CustomEvent('kill-all-sessions'));
// Reset after a delay to prevent multiple clicks
window.setTimeout(() => {
this.killingAll = false;
}, TIMING.KILL_ALL_BUTTON_DISABLE_DURATION);
}
protected handleCleanExited() {
this.dispatchEvent(new CustomEvent('clean-exited-sessions'));
}
protected handleHideExitedToggle() {
this.dispatchEvent(
new CustomEvent('hide-exited-change', {
detail: !this.hideExited,
})
);
}
protected handleOpenFileBrowser() {
this.dispatchEvent(new CustomEvent('open-file-browser'));
}
protected handleOpenSettings() {
this.showUserMenu = false;
this.dispatchEvent(new CustomEvent('open-settings'));
}
protected handleLogout() {
this.showUserMenu = false;
this.dispatchEvent(new CustomEvent('logout'));
}
protected handleScreenshare() {
// Dispatch event to start screenshare
this.dispatchEvent(
new CustomEvent('start-screenshare', {
bubbles: true,
composed: true,
})
);
}
protected toggleUserMenu() {
this.showUserMenu = !this.showUserMenu;
}
protected handleHomeClick() {
this.dispatchEvent(new CustomEvent('navigate-to-list'));
}
protected handleClickOutside = (e: Event) => {
const target = e.target as HTMLElement;
if (!target.closest('.user-menu-container')) {
this.showUserMenu = false;
}
};
connectedCallback() {
super.connectedCallback();
document.addEventListener('click', this.handleClickOutside);
}
disconnectedCallback() {
super.disconnectedCallback();
document.removeEventListener('click', this.handleClickOutside);
}
}