fix: gate Neovim control behind live sync

This commit is contained in:
user
2026-07-17 07:56:19 +02:00
parent 182f01fc5e
commit 94e77f1abf
2 changed files with 34 additions and 8 deletions
+27 -8
View File
@@ -326,9 +326,14 @@ function Topbar({
type="button"
className={`nvim-work-indicator${nvimControlMode ? " is-active" : ""}${nvimSummary.controlEnabled ? " is-engaged" : ""}`}
aria-pressed={nvimControlMode}
disabled={!nvimSyncMode}
onClick={() => setNvimControlMode(!nvimControlMode)}
>
{nvimControlMode ? "Alt+3 · STEROWANIE ON" : "Alt+3 · STEROWANIE OFF"}
{!nvimSyncMode
? "Alt+3 · STEROWANIE NIEDOSTĘPNE"
: nvimControlMode
? "Alt+3 · STEROWANIE ON"
: "Alt+3 · STEROWANIE OFF"}
</button>
<button
type="button"
@@ -1155,10 +1160,13 @@ function NeovimPanel({
}, [controlEnabled]);
useEffect(() => {
if (!visible) {
if (!visible || !syncMode) {
websocketRef.current?.close();
websocketRef.current = null;
setStatus({ state: "hidden" });
setPointerInside(false);
setStatus(visible
? { state: "offline", message: "SYNC OFF: pokazuję zapisany ekran bez połączenia z kontenerem." }
: { state: "hidden" });
return;
}
let cancelled = false;
@@ -1221,7 +1229,7 @@ function NeovimPanel({
websocketRef.current?.close();
websocketRef.current = null;
};
}, [visible]);
}, [syncMode, visible]);
if (!visible) return null;
const send = (message: object) => {
@@ -2819,7 +2827,8 @@ function App({ model }: { model: CardModel }) {
() => localStorage.getItem("stem-card-nvim-sync-mode") === "true",
);
const [nvimControlMode, setNvimControlModeState] = useState(
() => localStorage.getItem("stem-card-nvim-control-mode") === "true",
() => localStorage.getItem("stem-card-nvim-sync-mode") === "true"
&& localStorage.getItem("stem-card-nvim-control-mode") === "true",
);
const [nvimExpanded, setNvimExpandedState] = useState(false);
const [nvimFit, setNvimFitState] = useState(false);
@@ -2850,12 +2859,17 @@ function App({ model }: { model: CardModel }) {
localStorage.setItem("stem-card-nvim-visible", String(value));
};
const setNvimControlMode = (value: boolean) => {
setNvimControlModeState(value);
localStorage.setItem("stem-card-nvim-control-mode", String(value));
const next = value && nvimSyncMode;
setNvimControlModeState(next);
localStorage.setItem("stem-card-nvim-control-mode", String(next));
};
const setNvimSyncMode = (value: boolean) => {
setNvimSyncModeState(value);
localStorage.setItem("stem-card-nvim-sync-mode", String(value));
if (!value) {
setNvimControlModeState(false);
localStorage.setItem("stem-card-nvim-control-mode", "false");
}
};
const setNvimExpanded = (value: boolean) => {
if (value) setNvimVisible(true);
@@ -2918,6 +2932,10 @@ function App({ model }: { model: CardModel }) {
setNvimSyncModeState(current => {
const next = !current;
localStorage.setItem("stem-card-nvim-sync-mode", String(next));
if (!next) {
setNvimControlModeState(false);
localStorage.setItem("stem-card-nvim-control-mode", "false");
}
return next;
});
return;
@@ -2925,6 +2943,7 @@ function App({ model }: { model: CardModel }) {
if (browserCommand === "Digit3") {
event.preventDefault();
event.stopImmediatePropagation();
if (!nvimSyncMode) return;
setNvimVisibleState(true);
localStorage.setItem("stem-card-nvim-visible", "true");
setNvimControlModeState(current => {
@@ -2995,7 +3014,7 @@ function App({ model }: { model: CardModel }) {
};
window.addEventListener("keydown", navigate, true);
return () => window.removeEventListener("keydown", navigate, true);
}, [shortcutsOpen]);
}, [nvimSyncMode, shortcutsOpen]);
useEffect(() => {
const wheel = (event: WheelEvent) => {
if (!event.altKey || event.ctrlKey) return;
+7
View File
@@ -182,6 +182,13 @@
.nvim-work-indicator.is-engaged {
box-shadow: inset 0 0 0 1px #cf3d31;
}
.nvim-work-indicator:disabled {
border-color: #a8b0b4;
background: #e6e9ea;
color: #7c878c;
cursor: not-allowed;
opacity: .8;
}
.nvim-height-toggle {
flex: none;
border: 1px solid #75848b;