Hide screen sharing button when Mac app is not connected (#367)

This commit is contained in:
Peter Steinberger 2025-07-16 03:37:33 +02:00 committed by GitHub
parent 12a2468f01
commit 500c75ebc8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 78 additions and 32 deletions

3
mac/.gitignore vendored
View file

@ -33,6 +33,9 @@ VibeTunnel/Local.xcconfig
# Build output
build_output.txt
# Release state - temporary file
.release-state.json
# Sparkle private key - NEVER commit this!
sparkle-private-ed-key.pem
sparkle-private-key-KEEP-SECURE.txt

View file

@ -93,6 +93,7 @@ export class SessionView extends LitElement {
@state() private terminalTheme: TerminalThemeId = 'auto';
@state() private terminalContainerHeight = '100%';
@state() private isLandscape = false;
@state() private macAppConnected = false;
private preferencesManager = TerminalPreferencesManager.getInstance();
@ -199,6 +200,9 @@ export class SessionView extends LitElement {
super.connectedCallback();
this.connected = true;
// Check server status to see if Mac app is connected
this.checkServerStatus();
// Check initial orientation
this.checkOrientation();
@ -611,6 +615,11 @@ export class SessionView extends LitElement {
}
private handleScreenshare() {
// Only allow screenshare if Mac app is connected
if (!this.macAppConnected) {
logger.warn('Screenshare requested but Mac app is not connected');
return;
}
// Dispatch event to start screenshare
this.dispatchEvent(
new CustomEvent('start-screenshare', {
@ -620,6 +629,23 @@ export class SessionView extends LitElement {
);
}
private async checkServerStatus() {
try {
const response = await fetch('/api/server/status', {
headers: authClient.getAuthHeader(),
});
if (response.ok) {
const status = await response.json();
this.macAppConnected = status.macAppConnected || false;
logger.debug('server status:', status);
}
} catch (error) {
logger.warn('failed to check server status:', error);
// Default to not connected if we can't check
this.macAppConnected = false;
}
}
private handleOpenSettings() {
// Dispatch event to open settings modal
this.dispatchEvent(
@ -1293,6 +1319,7 @@ export class SessionView extends LitElement {
.onFontSizeChange=${(size: number) => this.handleFontSizeChange(size)}
.onScreenshare=${() => this.handleScreenshare()}
.onOpenSettings=${() => this.handleOpenSettings()}
.macAppConnected=${this.macAppConnected}
@close-width-selector=${() => {
this.showWidthSelector = false;
this.customWidth = '';

View file

@ -26,6 +26,7 @@ export class MobileMenu extends LitElement {
@property({ type: Function }) onMaxWidthToggle?: () => void;
@property({ type: Function }) onOpenSettings?: () => void;
@property({ type: String }) currentTheme: Theme = 'system';
@property({ type: Boolean }) macAppConnected = false;
@state() private showMenu = false;
@state() private focusedIndex = -1;
@ -225,6 +226,7 @@ export class MobileMenu extends LitElement {
}
private renderDropdown() {
let menuItemIndex = 0;
return html`
<div
class="absolute right-0 top-full mt-2 bg-surface border border-base rounded-lg shadow-xl py-1 min-w-[200px]"
@ -233,7 +235,7 @@ export class MobileMenu extends LitElement {
<!-- New Session -->
<button
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === 0 ? 'bg-secondary text-primary' : ''}"
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
@click=${() => this.handleAction(this.onCreateSession)}
data-testid="mobile-new-session"
tabindex="${this.showMenu ? '0' : '-1'}"
@ -248,7 +250,7 @@ export class MobileMenu extends LitElement {
<!-- File Browser -->
<button
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === 1 ? 'bg-secondary text-primary' : ''}"
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
@click=${() => this.handleAction(this.onOpenFileBrowser)}
data-testid="mobile-file-browser"
tabindex="${this.showMenu ? '0' : '-1'}"
@ -259,25 +261,31 @@ export class MobileMenu extends LitElement {
Browse Files
</button>
<!-- Screenshare -->
<button
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === 2 ? 'bg-secondary text-primary' : ''}"
@click=${() => this.handleAction(this.onScreenshare)}
data-testid="mobile-screenshare"
tabindex="${this.showMenu ? '0' : '-1'}"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="20" height="14" rx="2"/>
<line x1="8" y1="21" x2="16" y2="21"/>
<line x1="12" y1="17" x2="12" y2="21"/>
<circle cx="12" cy="10" r="3" fill="currentColor" stroke="none"/>
</svg>
Screenshare
</button>
<!-- Screenshare - only show if Mac app is connected -->
${
this.macAppConnected
? html`
<button
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
@click=${() => this.handleAction(this.onScreenshare)}
data-testid="mobile-screenshare"
tabindex="${this.showMenu ? '0' : '-1'}"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="20" height="14" rx="2"/>
<line x1="8" y1="21" x2="16" y2="21"/>
<line x1="12" y1="17" x2="12" y2="21"/>
<circle cx="12" cy="10" r="3" fill="currentColor" stroke="none"/>
</svg>
Screenshare
</button>
`
: ''
}
<!-- Width Settings -->
<button
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === 3 ? 'bg-secondary text-primary' : ''}"
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
@click=${() => this.handleAction(this.onMaxWidthToggle)}
data-testid="mobile-width-settings"
tabindex="${this.showMenu ? '0' : '-1'}"
@ -290,7 +298,7 @@ export class MobileMenu extends LitElement {
<!-- Theme Toggle -->
<button
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === 4 ? 'bg-secondary text-primary' : ''}"
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
@click=${() => this.handleThemeChange()}
data-testid="mobile-theme-toggle"
tabindex="${this.showMenu ? '0' : '-1'}"
@ -301,7 +309,7 @@ export class MobileMenu extends LitElement {
<!-- Settings -->
<button
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === 5 ? 'bg-secondary text-primary' : ''}"
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
@click=${() => this.handleAction(this.onOpenSettings)}
data-testid="mobile-settings"
tabindex="${this.showMenu ? '0' : '-1'}"

View file

@ -50,6 +50,7 @@ export class SessionHeader extends LitElement {
@property({ type: String }) currentTheme = 'system';
@property({ type: Boolean }) keyboardCaptureActive = true;
@property({ type: Boolean }) isMobile = false;
@property({ type: Boolean }) macAppConnected = false;
@state() private isHovered = false;
connectedCallback() {
@ -262,18 +263,24 @@ export class SessionHeader extends LitElement {
/>
</svg>
</button>
<button
class="bg-bg-tertiary border border-border rounded-lg p-2 font-mono text-muted transition-all duration-200 hover:text-primary hover:bg-surface-hover hover:border-primary hover:shadow-sm flex-shrink-0"
@click=${() => this.onScreenshare?.()}
title="Start Screenshare"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="20" height="14" rx="2"/>
<line x1="8" y1="21" x2="16" y2="21"/>
<line x1="12" y1="17" x2="12" y2="21"/>
<circle cx="12" cy="10" r="3" fill="currentColor" stroke="none"/>
</svg>
</button>
${
this.macAppConnected
? html`
<button
class="bg-bg-tertiary border border-border rounded-lg p-2 font-mono text-muted transition-all duration-200 hover:text-primary hover:bg-surface-hover hover:border-primary hover:shadow-sm flex-shrink-0"
@click=${() => this.onScreenshare?.()}
title="Start Screenshare"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="20" height="14" rx="2"/>
<line x1="8" y1="21" x2="16" y2="21"/>
<line x1="12" y1="17" x2="12" y2="21"/>
<circle cx="12" cy="10" r="3" fill="currentColor" stroke="none"/>
</svg>
</button>
`
: ''
}
<button
class="bg-bg-tertiary border border-border rounded-lg px-3 py-2 font-mono text-xs text-muted transition-all duration-200 hover:text-primary hover:bg-surface-hover hover:border-primary hover:shadow-sm flex-shrink-0 width-selector-button"
@click=${() => this.onMaxWidthToggle?.()}
@ -295,6 +302,7 @@ export class SessionHeader extends LitElement {
.onOpenSettings=${this.onOpenSettings}
.onCreateSession=${this.onCreateSession}
.currentTheme=${this.currentTheme}
.macAppConnected=${this.macAppConnected}
></mobile-menu>
</div>