import { useCallback, useEffect, useMemo, useState } from 'react';
import { api, isElectronMode } from '@renderer/api';
import { AlertTriangle, ExternalLink, RefreshCw, Wrench } from 'lucide-react';
import type { TmuxStatus } from '@shared/types';
const OFFICIAL_TMUX_INSTALL_URL = 'https://github.com/tmux/tmux/wiki/Installing';
type BannerState =
| { loading: true; status: null; error: null }
| { loading: false; status: TmuxStatus; error: null }
| { loading: false; status: null; error: string };
const INITIAL_STATE: BannerState = { loading: true, status: null, error: null };
const PlatformInstallMatrix = (): React.JSX.Element => {
return (
macOS
Homebrew
brew install tmux
MacPorts
port install tmux
Linux
apt install tmux
dnf install tmux
yum install tmux
zypper install tmux
pacman -S tmux
Windows
В official tmux wiki нет native Windows install command.
Рекомендуемый путь: WSL, затем внутри Linux-дистрибутива использовать одну из Linux
команд выше, например apt install tmux.
);
};
function getPrimaryDetail(status: TmuxStatus): string {
if (status.platform === 'darwin') {
return 'На macOS проще всего поставить tmux через Homebrew или MacPorts.';
}
if (status.platform === 'linux') {
return 'На Linux команда зависит от дистрибутива: apt, dnf, yum, zypper или pacman.';
}
if (status.platform === 'win32') {
return 'На Windows у official tmux wiki нет native installer; safest путь — WSL и установка tmux внутри Linux-дистрибутива.';
}
return 'Поставь tmux через пакетный менеджер своей ОС.';
}
export const TmuxStatusBanner = (): React.JSX.Element | null => {
const isElectron = useMemo(() => isElectronMode(), []);
const [state, setState] = useState(INITIAL_STATE);
const fetchStatus = useCallback(async () => {
setState(
(prev) =>
({
loading: true,
status: prev.status,
error: null,
}) as BannerState
);
try {
const status = await api.tmux.getStatus();
setState({ loading: false, status, error: null });
} catch (error) {
setState({
loading: false,
status: null,
error: error instanceof Error ? error.message : 'Failed to check tmux status',
});
}
}, []);
useEffect(() => {
if (!isElectron) {
return;
}
void fetchStatus();
}, [fetchStatus, isElectron]);
if (!isElectron) return null;
if (state.loading && !state.status) return null;
if (state.error && !state.status) {
return (
Failed to check tmux availability
{state.error}
void fetchStatus()}
className="flex shrink-0 items-center gap-1.5 rounded-md border px-3 py-1.5 text-xs font-medium transition-colors hover:bg-white/5"
style={{ borderColor: 'var(--color-border)', color: 'var(--color-text-secondary)' }}
>
Retry
);
}
if (!state.status || state.status.available) {
return null;
}
return (
tmux is not installed
Persistent team agents работают стабильнее в process/tmux path. Без tmux app остаётся
на более тяжёлом in-process пути. {getPrimaryDetail(state.status)}
{state.status.error && (
Last check error: {state.status.error}
)}
void fetchStatus()}
className="flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-xs font-medium transition-colors hover:bg-white/5"
style={{ borderColor: 'var(--color-border)', color: 'var(--color-text-secondary)' }}
>
Re-check
void api.openExternal(OFFICIAL_TMUX_INSTALL_URL)}
className="flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-xs font-medium transition-colors hover:bg-white/5"
style={{ borderColor: 'var(--color-border)', color: 'var(--color-text-secondary)' }}
>
Open guide
);
};