dmux 3.0.2 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DmuxApp.d.ts.map +1 -1
- package/dist/DmuxApp.js +242 -23
- package/dist/DmuxApp.js.map +1 -1
- package/dist/PaneAnalyzer.d.ts +0 -4
- package/dist/PaneAnalyzer.d.ts.map +1 -1
- package/dist/PaneAnalyzer.js +2 -17
- package/dist/PaneAnalyzer.js.map +1 -1
- package/dist/_plugin-vue_export-helper.css +1 -1
- package/dist/actions/paneActions.d.ts.map +1 -1
- package/dist/actions/paneActions.js +94 -40
- package/dist/actions/paneActions.js.map +1 -1
- package/dist/components/ActionConfirmDialog.js +1 -1
- package/dist/components/ActionConfirmDialog.js.map +1 -1
- package/dist/components/CloseOptionsDialog.d.ts.map +1 -1
- package/dist/components/CloseOptionsDialog.js +9 -7
- package/dist/components/CloseOptionsDialog.js.map +1 -1
- package/dist/components/FooterHelp.js +1 -1
- package/dist/components/FooterHelp.js.map +1 -1
- package/dist/components/HooksDialog.d.ts +12 -0
- package/dist/components/HooksDialog.d.ts.map +1 -0
- package/dist/components/HooksDialog.js +52 -0
- package/dist/components/HooksDialog.js.map +1 -0
- package/dist/components/MergeConfirmationDialog.d.ts.map +1 -1
- package/dist/components/MergeConfirmationDialog.js +2 -1
- package/dist/components/MergeConfirmationDialog.js.map +1 -1
- package/dist/components/NewPaneDialog.d.ts.map +1 -1
- package/dist/components/NewPaneDialog.js +1 -3
- package/dist/components/NewPaneDialog.js.map +1 -1
- package/dist/components/SettingsDialog.d.ts +16 -0
- package/dist/components/SettingsDialog.d.ts.map +1 -0
- package/dist/components/SettingsDialog.js +95 -0
- package/dist/components/SettingsDialog.js.map +1 -0
- package/dist/dashboard.js +2 -2
- package/dist/hooks/useAutoUpdater.js +2 -2
- package/dist/hooks/useAutoUpdater.js.map +1 -1
- package/dist/hooks/usePaneCreation.d.ts.map +1 -1
- package/dist/hooks/usePaneCreation.js +22 -3
- package/dist/hooks/usePaneCreation.js.map +1 -1
- package/dist/hooks/usePanes.js +2 -2
- package/dist/hooks/usePanes.js.map +1 -1
- package/dist/hooks/useTerminalWidth.d.ts.map +1 -1
- package/dist/hooks/useTerminalWidth.js +5 -0
- package/dist/hooks/useTerminalWidth.js.map +1 -1
- package/dist/hooks/useWorktreeActions.js +4 -4
- package/dist/hooks/useWorktreeActions.js.map +1 -1
- package/dist/server/embedded-assets.d.ts.map +1 -1
- package/dist/server/embedded-assets.js +251 -47
- package/dist/server/embedded-assets.js.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +195 -55
- package/dist/server/routes.js.map +1 -1
- package/dist/services/ConfigWatcher.d.ts +9 -0
- package/dist/services/ConfigWatcher.d.ts.map +1 -1
- package/dist/services/ConfigWatcher.js +17 -0
- package/dist/services/ConfigWatcher.js.map +1 -1
- package/dist/services/StatusDetector.js +7 -7
- package/dist/services/StatusDetector.js.map +1 -1
- package/dist/services/TunnelService.d.ts.map +1 -1
- package/dist/services/TunnelService.js +25 -3
- package/dist/services/TunnelService.js.map +1 -1
- package/dist/shared/StateManager.d.ts +11 -0
- package/dist/shared/StateManager.d.ts.map +1 -1
- package/dist/shared/StateManager.js +26 -0
- package/dist/shared/StateManager.js.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/conflictResolutionPane.d.ts.map +1 -1
- package/dist/utils/conflictResolutionPane.js +3 -2
- package/dist/utils/conflictResolutionPane.js.map +1 -1
- package/dist/utils/generated-agents-doc.d.ts +6 -0
- package/dist/utils/generated-agents-doc.d.ts.map +1 -0
- package/dist/utils/generated-agents-doc.js +430 -0
- package/dist/utils/generated-agents-doc.js.map +1 -0
- package/dist/utils/hooks.d.ts +70 -0
- package/dist/utils/hooks.d.ts.map +1 -0
- package/dist/utils/hooks.js +216 -0
- package/dist/utils/hooks.js.map +1 -0
- package/dist/utils/hooksDocs.d.ts +42 -0
- package/dist/utils/hooksDocs.d.ts.map +1 -0
- package/dist/utils/hooksDocs.js +325 -0
- package/dist/utils/hooksDocs.js.map +1 -0
- package/dist/utils/paneCapture.d.ts +21 -0
- package/dist/utils/paneCapture.d.ts.map +1 -0
- package/dist/utils/paneCapture.js +96 -0
- package/dist/utils/paneCapture.js.map +1 -0
- package/dist/utils/paneCreation.d.ts +1 -0
- package/dist/utils/paneCreation.d.ts.map +1 -1
- package/dist/utils/paneCreation.js +90 -18
- package/dist/utils/paneCreation.js.map +1 -1
- package/dist/utils/settingsManager.d.ts +49 -0
- package/dist/utils/settingsManager.d.ts.map +1 -0
- package/dist/utils/settingsManager.js +172 -0
- package/dist/utils/settingsManager.js.map +1 -0
- package/dist/utils/tmux.d.ts.map +1 -1
- package/dist/utils/tmux.js +79 -20
- package/dist/utils/tmux.js.map +1 -1
- package/dist/workers/PaneWorker.js +3 -6
- package/dist/workers/PaneWorker.js.map +1 -1
- package/package.json +4 -3
package/dist/DmuxApp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DmuxApp.d.ts","sourceRoot":"","sources":["../src/DmuxApp.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"DmuxApp.d.ts","sourceRoot":"","sources":["../src/DmuxApp.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAgCnD,OAAO,KAAK,EAA2C,YAAY,EAAE,MAAM,YAAY,CAAC;AAqBxF,QAAA,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA4gDnC,CAAC;AAEF,eAAe,OAAO,CAAC"}
|
package/dist/DmuxApp.js
CHANGED
|
@@ -19,9 +19,11 @@ import { applySmartLayout } from './utils/tmux.js';
|
|
|
19
19
|
import { suggestCommand } from './utils/commands.js';
|
|
20
20
|
import { generateSlug } from './utils/slug.js';
|
|
21
21
|
import { getMainBranch } from './utils/git.js';
|
|
22
|
+
import { capturePaneContent } from './utils/paneCapture.js';
|
|
22
23
|
import { StateManager } from './shared/StateManager.js';
|
|
23
24
|
import { getStatusDetector } from './services/StatusDetector.js';
|
|
24
25
|
import { PaneAction, getAvailableActions } from './actions/index.js';
|
|
26
|
+
import { SettingsManager, SETTING_DEFINITIONS } from './utils/settingsManager.js';
|
|
25
27
|
const require = createRequire(import.meta.url);
|
|
26
28
|
const packageJson = require('../package.json');
|
|
27
29
|
import PanesGrid from './components/PanesGrid.js';
|
|
@@ -40,7 +42,9 @@ import ActionChoiceDialog from './components/ActionChoiceDialog.js';
|
|
|
40
42
|
import ActionConfirmDialog from './components/ActionConfirmDialog.js';
|
|
41
43
|
import ActionInputDialog from './components/ActionInputDialog.js';
|
|
42
44
|
import ActionProgressDialog from './components/ActionProgressDialog.js';
|
|
43
|
-
|
|
45
|
+
import SettingsDialog from './components/SettingsDialog.js';
|
|
46
|
+
import HooksDialog from './components/HooksDialog.js';
|
|
47
|
+
const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, projectRoot, autoUpdater, serverPort, server }) => {
|
|
44
48
|
/* panes state moved to usePanes */
|
|
45
49
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
46
50
|
const [showNewPaneDialog, setShowNewPaneDialog] = useState(false);
|
|
@@ -50,9 +54,23 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
50
54
|
const [showQRCode, setShowQRCode] = useState(false);
|
|
51
55
|
const [tunnelUrl, setTunnelUrl] = useState(null);
|
|
52
56
|
const [isCreatingTunnel, setIsCreatingTunnel] = useState(false);
|
|
57
|
+
// Settings state
|
|
58
|
+
const [settingsManager] = useState(() => new SettingsManager(projectRoot));
|
|
59
|
+
const [showSettingsDialog, setShowSettingsDialog] = useState(false);
|
|
60
|
+
const [settingsMode, setSettingsMode] = useState('list');
|
|
61
|
+
const [settingsSelectedIndex, setSettingsSelectedIndex] = useState(0);
|
|
62
|
+
const [settingsEditingKey, setSettingsEditingKey] = useState();
|
|
63
|
+
const [settingsEditingValueIndex, setSettingsEditingValueIndex] = useState(0);
|
|
64
|
+
const [settingsScopeIndex, setSettingsScopeIndex] = useState(0);
|
|
53
65
|
// Force repaint trigger - incrementing this causes Ink to re-render
|
|
54
66
|
const [forceRepaintTrigger, setForceRepaintTrigger] = useState(0);
|
|
67
|
+
// Spinner state - shows for a few frames to force render
|
|
68
|
+
const [showRepaintSpinner, setShowRepaintSpinner] = useState(false);
|
|
55
69
|
const { projectSettings, saveSettings } = useProjectSettings(settingsFile);
|
|
70
|
+
// Hooks management state
|
|
71
|
+
const [showHooksDialog, setShowHooksDialog] = useState(false);
|
|
72
|
+
const [hooksSelectedIndex, setHooksSelectedIndex] = useState(0);
|
|
73
|
+
const [hooksData, setHooksData] = useState([]);
|
|
56
74
|
const [showCommandPrompt, setShowCommandPrompt] = useState(null);
|
|
57
75
|
const [commandInput, setCommandInput] = useState('');
|
|
58
76
|
const [showFileCopyPrompt, setShowFileCopyPrompt] = useState(false);
|
|
@@ -63,6 +81,8 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
63
81
|
const [kebabMenuPaneIndex, setKebabMenuPaneIndex] = useState(null);
|
|
64
82
|
const [kebabMenuOption, setKebabMenuOption] = useState(0);
|
|
65
83
|
const [kebabMenuActions, setKebabMenuActions] = useState([]);
|
|
84
|
+
// Debug message state - for temporary logging messages
|
|
85
|
+
const [debugMessage, setDebugMessage] = useState('');
|
|
66
86
|
// Update state handled by hook
|
|
67
87
|
const { updateInfo, showUpdateDialog, isUpdating, performUpdate, skipUpdate, dismissUpdate, updateAvailable } = useAutoUpdater(autoUpdater, setStatusMessage);
|
|
68
88
|
const { exit } = useApp();
|
|
@@ -104,8 +124,13 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
104
124
|
setStatusMessage,
|
|
105
125
|
setRunningCommand,
|
|
106
126
|
});
|
|
107
|
-
// Force repaint helper
|
|
108
|
-
const forceRepaint = () =>
|
|
127
|
+
// Force repaint helper - shows spinner for a few frames to force full re-render
|
|
128
|
+
const forceRepaint = () => {
|
|
129
|
+
setForceRepaintTrigger(prev => prev + 1);
|
|
130
|
+
setShowRepaintSpinner(true);
|
|
131
|
+
// Hide spinner after a few frames (enough to trigger multiple renders)
|
|
132
|
+
setTimeout(() => setShowRepaintSpinner(false), 100);
|
|
133
|
+
};
|
|
109
134
|
// Force repaint effect - ensures Ink re-renders when trigger changes
|
|
110
135
|
useEffect(() => {
|
|
111
136
|
if (forceRepaintTrigger > 0) {
|
|
@@ -120,7 +145,7 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
120
145
|
}
|
|
121
146
|
}, [forceRepaintTrigger]);
|
|
122
147
|
// Pane creation
|
|
123
|
-
const {
|
|
148
|
+
const { createNewPane: createNewPaneHook } = usePaneCreation({
|
|
124
149
|
panes,
|
|
125
150
|
savePanes,
|
|
126
151
|
projectName,
|
|
@@ -204,6 +229,14 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
204
229
|
const stateManager = StateManager.getInstance();
|
|
205
230
|
stateManager.updateSettings(projectSettings);
|
|
206
231
|
}, [projectSettings]);
|
|
232
|
+
// Expose debug message setter via StateManager
|
|
233
|
+
useEffect(() => {
|
|
234
|
+
const stateManager = StateManager.getInstance();
|
|
235
|
+
stateManager.setDebugMessageCallback(setDebugMessage);
|
|
236
|
+
return () => {
|
|
237
|
+
stateManager.setDebugMessageCallback(undefined);
|
|
238
|
+
};
|
|
239
|
+
}, []);
|
|
207
240
|
// Load panes and settings on mount and refresh periodically
|
|
208
241
|
useEffect(() => {
|
|
209
242
|
// SIGTERM should quit immediately (for process management)
|
|
@@ -211,6 +244,11 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
211
244
|
cleanExit();
|
|
212
245
|
};
|
|
213
246
|
process.on('SIGTERM', handleTermination);
|
|
247
|
+
// Test debug message on mount
|
|
248
|
+
StateManager.getInstance().setDebugMessage('Debug logging initialized - watching for AI activity...');
|
|
249
|
+
setTimeout(() => {
|
|
250
|
+
StateManager.getInstance().setDebugMessage('');
|
|
251
|
+
}, 3000);
|
|
214
252
|
return () => {
|
|
215
253
|
process.removeListener('SIGTERM', handleTermination);
|
|
216
254
|
};
|
|
@@ -432,8 +470,7 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
432
470
|
await new Promise(resolve => setTimeout(resolve, checkInterval));
|
|
433
471
|
try {
|
|
434
472
|
// Capture the pane content
|
|
435
|
-
const paneContent =
|
|
436
|
-
{ encoding: 'utf-8', stdio: 'pipe' });
|
|
473
|
+
const paneContent = capturePaneContent(paneInfo, 30);
|
|
437
474
|
if (i % 10 === 0) { // Log every 10 checks (every second)
|
|
438
475
|
}
|
|
439
476
|
// Check if content has stabilized (same for 3 checks = prompt is waiting)
|
|
@@ -477,7 +514,7 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
477
514
|
// Wait and check if prompt is gone
|
|
478
515
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
479
516
|
// Verify the prompt is gone
|
|
480
|
-
const updatedContent =
|
|
517
|
+
const updatedContent = capturePaneContent(paneInfo, 10);
|
|
481
518
|
// If trust prompt is gone, check if we need to resend the Claude command
|
|
482
519
|
const promptGone = !trustPromptPatterns.some(p => p.test(updatedContent));
|
|
483
520
|
if (promptGone) {
|
|
@@ -551,6 +588,8 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
551
588
|
// Ignore if already set or fails
|
|
552
589
|
}
|
|
553
590
|
execSync(`tmux select-pane -t '${paneId}'`, { stdio: 'pipe' });
|
|
591
|
+
// Clear screen after jump to remove artifacts
|
|
592
|
+
clearScreen();
|
|
554
593
|
setStatusMessage('Jumped to pane');
|
|
555
594
|
setTimeout(() => setStatusMessage(''), 2000);
|
|
556
595
|
}
|
|
@@ -634,6 +673,9 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
634
673
|
// Update handling moved to useAutoUpdater
|
|
635
674
|
// Helper function to clear screen artifacts
|
|
636
675
|
const clearScreen = () => {
|
|
676
|
+
// CRITICAL: Force Ink to re-render FIRST, before clearing
|
|
677
|
+
// This prevents blank screen by ensuring React starts rendering immediately
|
|
678
|
+
setForceRepaintTrigger(prev => prev + 1);
|
|
637
679
|
// Multiple clearing strategies to prevent artifacts
|
|
638
680
|
// 1. Clear screen with ANSI codes
|
|
639
681
|
process.stdout.write('\x1b[2J\x1b[H');
|
|
@@ -647,12 +689,6 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
647
689
|
execSync('tmux refresh-client', { stdio: 'pipe' });
|
|
648
690
|
}
|
|
649
691
|
catch { }
|
|
650
|
-
// 4. Force Ink to repaint after clearing with a delay
|
|
651
|
-
// This prevents the blank screen bug by ensuring Ink re-renders
|
|
652
|
-
// after the terminal has processed the clear operations
|
|
653
|
-
setTimeout(() => {
|
|
654
|
-
setForceRepaintTrigger(prev => prev + 1);
|
|
655
|
-
}, 200);
|
|
656
692
|
};
|
|
657
693
|
// Cleanup function for exit
|
|
658
694
|
const cleanExit = () => {
|
|
@@ -710,7 +746,6 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
710
746
|
setKebabMenuPaneIndex(null);
|
|
711
747
|
setKebabMenuOption(0);
|
|
712
748
|
setKebabMenuActions([]);
|
|
713
|
-
clearScreen();
|
|
714
749
|
return;
|
|
715
750
|
}
|
|
716
751
|
else if (key.upArrow) {
|
|
@@ -724,7 +759,6 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
724
759
|
else if (key.return) {
|
|
725
760
|
// Execute the selected menu action
|
|
726
761
|
setShowKebabMenu(false);
|
|
727
|
-
clearScreen();
|
|
728
762
|
const selectedAction = availableActions[kebabMenuOption];
|
|
729
763
|
if (selectedAction) {
|
|
730
764
|
// Use the action system to execute
|
|
@@ -753,6 +787,173 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
753
787
|
}
|
|
754
788
|
return;
|
|
755
789
|
}
|
|
790
|
+
// Handle hooks dialog
|
|
791
|
+
if (showHooksDialog) {
|
|
792
|
+
if (key.escape) {
|
|
793
|
+
setShowHooksDialog(false);
|
|
794
|
+
setHooksSelectedIndex(0);
|
|
795
|
+
// Go back to settings dialog
|
|
796
|
+
setShowSettingsDialog(true);
|
|
797
|
+
setSettingsMode('list');
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
else if (key.upArrow) {
|
|
801
|
+
setHooksSelectedIndex(Math.max(0, hooksSelectedIndex - 1));
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
else if (key.downArrow) {
|
|
805
|
+
setHooksSelectedIndex(Math.min(hooksData.length - 1, hooksSelectedIndex + 1));
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
else if (input === 'e') {
|
|
809
|
+
// Edit hooks using an agent
|
|
810
|
+
setShowHooksDialog(false);
|
|
811
|
+
setHooksSelectedIndex(0);
|
|
812
|
+
const prompt = "I would like to edit my dmux hooks in .dmux-hooks, please read the instructions in there and ask me what I want to edit";
|
|
813
|
+
setPendingPrompt(prompt);
|
|
814
|
+
setNewPanePrompt(prompt);
|
|
815
|
+
// Choose agent
|
|
816
|
+
const agents = availableAgents;
|
|
817
|
+
if (agents.length === 0) {
|
|
818
|
+
createNewPaneHook(prompt);
|
|
819
|
+
}
|
|
820
|
+
else if (agents.length === 1) {
|
|
821
|
+
createNewPaneHook(prompt, agents[0]);
|
|
822
|
+
}
|
|
823
|
+
else {
|
|
824
|
+
setShowAgentChoiceDialog(true);
|
|
825
|
+
setAgentChoice(agentChoice || 'claude');
|
|
826
|
+
}
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
// Handle settings dialog
|
|
832
|
+
if (showSettingsDialog) {
|
|
833
|
+
if (key.escape) {
|
|
834
|
+
if (settingsMode === 'list') {
|
|
835
|
+
// Close settings dialog
|
|
836
|
+
setShowSettingsDialog(false);
|
|
837
|
+
setSettingsMode('list');
|
|
838
|
+
setSettingsSelectedIndex(0);
|
|
839
|
+
setSettingsEditingKey(undefined);
|
|
840
|
+
}
|
|
841
|
+
else {
|
|
842
|
+
// Go back to list
|
|
843
|
+
setSettingsMode('list');
|
|
844
|
+
setSettingsEditingKey(undefined);
|
|
845
|
+
setSettingsEditingValueIndex(0);
|
|
846
|
+
setSettingsScopeIndex(0);
|
|
847
|
+
}
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
else if (key.upArrow) {
|
|
851
|
+
if (settingsMode === 'list') {
|
|
852
|
+
setSettingsSelectedIndex(Math.max(0, settingsSelectedIndex - 1));
|
|
853
|
+
}
|
|
854
|
+
else if (settingsMode === 'edit') {
|
|
855
|
+
const currentDef = SETTING_DEFINITIONS[settingsSelectedIndex];
|
|
856
|
+
const maxIndex = currentDef.type === 'boolean' ? 1 : (currentDef.options?.length || 1) - 1;
|
|
857
|
+
setSettingsEditingValueIndex(Math.max(0, settingsEditingValueIndex - 1));
|
|
858
|
+
}
|
|
859
|
+
else if (settingsMode === 'scope') {
|
|
860
|
+
setSettingsScopeIndex(Math.max(0, settingsScopeIndex - 1));
|
|
861
|
+
}
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
else if (key.downArrow) {
|
|
865
|
+
if (settingsMode === 'list') {
|
|
866
|
+
setSettingsSelectedIndex(Math.min(SETTING_DEFINITIONS.length - 1, settingsSelectedIndex + 1));
|
|
867
|
+
}
|
|
868
|
+
else if (settingsMode === 'edit') {
|
|
869
|
+
const currentDef = SETTING_DEFINITIONS[settingsSelectedIndex];
|
|
870
|
+
const maxIndex = currentDef.type === 'boolean' ? 1 : (currentDef.options?.length || 1) - 1;
|
|
871
|
+
setSettingsEditingValueIndex(Math.min(maxIndex, settingsEditingValueIndex + 1));
|
|
872
|
+
}
|
|
873
|
+
else if (settingsMode === 'scope') {
|
|
874
|
+
setSettingsScopeIndex(Math.min(1, settingsScopeIndex + 1));
|
|
875
|
+
}
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
else if (key.return) {
|
|
879
|
+
if (settingsMode === 'list') {
|
|
880
|
+
const currentDef = SETTING_DEFINITIONS[settingsSelectedIndex];
|
|
881
|
+
// Handle action type - trigger the action instead of editing
|
|
882
|
+
if (currentDef.type === 'action') {
|
|
883
|
+
if (currentDef.key === 'hooks') {
|
|
884
|
+
// Show hooks dialog
|
|
885
|
+
setShowSettingsDialog(false);
|
|
886
|
+
const { hasHook } = await import('./utils/hooks.js');
|
|
887
|
+
const allHookTypes = [
|
|
888
|
+
'before_pane_create',
|
|
889
|
+
'pane_created',
|
|
890
|
+
'worktree_created',
|
|
891
|
+
'before_pane_close',
|
|
892
|
+
'pane_closed',
|
|
893
|
+
'before_worktree_remove',
|
|
894
|
+
'worktree_removed',
|
|
895
|
+
'pre_merge',
|
|
896
|
+
'post_merge',
|
|
897
|
+
'run_test',
|
|
898
|
+
'run_dev',
|
|
899
|
+
];
|
|
900
|
+
const hooks = allHookTypes.map(hookName => ({
|
|
901
|
+
name: hookName,
|
|
902
|
+
active: hasHook(projectRoot || process.cwd(), hookName)
|
|
903
|
+
}));
|
|
904
|
+
setHooksData(hooks);
|
|
905
|
+
setShowHooksDialog(true);
|
|
906
|
+
setHooksSelectedIndex(0);
|
|
907
|
+
}
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
// Enter edit mode for regular settings
|
|
911
|
+
setSettingsEditingKey(currentDef.key);
|
|
912
|
+
setSettingsMode('edit');
|
|
913
|
+
// Set initial value index based on current setting
|
|
914
|
+
const currentValue = settingsManager.getSetting(currentDef.key);
|
|
915
|
+
if (currentDef.type === 'boolean') {
|
|
916
|
+
setSettingsEditingValueIndex(currentValue ? 0 : 1);
|
|
917
|
+
}
|
|
918
|
+
else if (currentDef.type === 'select' && currentDef.options) {
|
|
919
|
+
const optIndex = currentDef.options.findIndex(o => o.value === currentValue);
|
|
920
|
+
setSettingsEditingValueIndex(Math.max(0, optIndex));
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
else if (settingsMode === 'edit') {
|
|
924
|
+
// Go to scope selection
|
|
925
|
+
setSettingsMode('scope');
|
|
926
|
+
setSettingsScopeIndex(0);
|
|
927
|
+
}
|
|
928
|
+
else if (settingsMode === 'scope') {
|
|
929
|
+
// Save the setting
|
|
930
|
+
const currentDef = SETTING_DEFINITIONS[settingsSelectedIndex];
|
|
931
|
+
const scope = settingsScopeIndex === 0 ? 'global' : 'project';
|
|
932
|
+
// Only save if this is not an action type (actions don't have values)
|
|
933
|
+
if (currentDef.type !== 'action') {
|
|
934
|
+
// Calculate the new value
|
|
935
|
+
let newValue;
|
|
936
|
+
if (currentDef.type === 'boolean') {
|
|
937
|
+
newValue = settingsEditingValueIndex === 0;
|
|
938
|
+
}
|
|
939
|
+
else if (currentDef.type === 'select' && currentDef.options) {
|
|
940
|
+
newValue = currentDef.options[settingsEditingValueIndex]?.value || '';
|
|
941
|
+
}
|
|
942
|
+
// Update the setting - cast key to proper type since we know it's not an action
|
|
943
|
+
settingsManager.updateSetting(currentDef.key, newValue, scope);
|
|
944
|
+
}
|
|
945
|
+
// Reset to list view
|
|
946
|
+
setSettingsMode('list');
|
|
947
|
+
setSettingsEditingKey(undefined);
|
|
948
|
+
setSettingsEditingValueIndex(0);
|
|
949
|
+
setSettingsScopeIndex(0);
|
|
950
|
+
setStatusMessage(`Setting saved (${scope})`);
|
|
951
|
+
setTimeout(() => setStatusMessage(''), 2000);
|
|
952
|
+
}
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
756
957
|
// Handle action system confirm dialog
|
|
757
958
|
if (actionSystem.actionState.showConfirmDialog) {
|
|
758
959
|
if (key.escape) {
|
|
@@ -911,7 +1112,7 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
911
1112
|
const promptValue = pendingPrompt;
|
|
912
1113
|
setShowAgentChoiceDialog(false);
|
|
913
1114
|
setPendingPrompt('');
|
|
914
|
-
await
|
|
1115
|
+
await createNewPaneHook(promptValue, chosen);
|
|
915
1116
|
setNewPanePrompt('');
|
|
916
1117
|
}
|
|
917
1118
|
return;
|
|
@@ -964,10 +1165,6 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
964
1165
|
setShowNewPaneDialog(false);
|
|
965
1166
|
setNewPanePrompt('');
|
|
966
1167
|
}
|
|
967
|
-
else if (key.ctrl && input === 'o') {
|
|
968
|
-
// Open in external editor
|
|
969
|
-
openEditor2(newPanePrompt, setNewPanePrompt);
|
|
970
|
-
}
|
|
971
1168
|
// TextInput handles other input events
|
|
972
1169
|
return;
|
|
973
1170
|
}
|
|
@@ -1000,6 +1197,12 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
1000
1197
|
setKebabMenuPaneIndex(selectedIndex);
|
|
1001
1198
|
setKebabMenuOption(0);
|
|
1002
1199
|
}
|
|
1200
|
+
else if (input === 's') {
|
|
1201
|
+
// Open settings dialog
|
|
1202
|
+
setShowSettingsDialog(true);
|
|
1203
|
+
setSettingsMode('list');
|
|
1204
|
+
setSettingsSelectedIndex(0);
|
|
1205
|
+
}
|
|
1003
1206
|
else if (input === 'q') {
|
|
1004
1207
|
cleanExit();
|
|
1005
1208
|
}
|
|
@@ -1035,14 +1238,20 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
1035
1238
|
}
|
|
1036
1239
|
else if (input === 'j' && selectedIndex < panes.length) {
|
|
1037
1240
|
// Jump to pane (NEW: using action system)
|
|
1241
|
+
StateManager.getInstance().setDebugMessage(`Jumping to pane: ${panes[selectedIndex].slug}`);
|
|
1242
|
+
setTimeout(() => StateManager.getInstance().setDebugMessage(''), 2000);
|
|
1038
1243
|
actionSystem.executeAction(PaneAction.VIEW, panes[selectedIndex]);
|
|
1039
1244
|
}
|
|
1040
1245
|
else if (input === 'x' && selectedIndex < panes.length) {
|
|
1041
1246
|
// Close pane (NEW: using action system)
|
|
1247
|
+
StateManager.getInstance().setDebugMessage(`Closing pane: ${panes[selectedIndex].slug}`);
|
|
1248
|
+
setTimeout(() => StateManager.getInstance().setDebugMessage(''), 2000);
|
|
1042
1249
|
actionSystem.executeAction(PaneAction.CLOSE, panes[selectedIndex]);
|
|
1043
1250
|
}
|
|
1044
1251
|
else if (key.return && selectedIndex < panes.length) {
|
|
1045
1252
|
// Jump to pane (NEW: using action system)
|
|
1253
|
+
StateManager.getInstance().setDebugMessage(`Jumping to pane: ${panes[selectedIndex].slug}`);
|
|
1254
|
+
setTimeout(() => StateManager.getInstance().setDebugMessage(''), 2000);
|
|
1046
1255
|
actionSystem.executeAction(PaneAction.VIEW, panes[selectedIndex]);
|
|
1047
1256
|
}
|
|
1048
1257
|
});
|
|
@@ -1056,6 +1265,8 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
1056
1265
|
React.createElement(Text, { dimColor: true }, "Press ESC to return to pane list"))));
|
|
1057
1266
|
}
|
|
1058
1267
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
1268
|
+
showRepaintSpinner && (React.createElement(Box, { marginTop: -10, marginLeft: -100 },
|
|
1269
|
+
React.createElement(Text, null, "\u27F3"))),
|
|
1059
1270
|
React.createElement(PanesGrid, { panes: panes, selectedIndex: selectedIndex, isLoading: isLoading, showNewPaneDialog: showNewPaneDialog, agentStatuses: agentStatuses, kebabMenuPaneIndex: kebabMenuPaneIndex ?? undefined }),
|
|
1060
1271
|
isLoading && (React.createElement(LoadingIndicator, null)),
|
|
1061
1272
|
showNewPaneDialog && !showAgentChoiceDialog && (React.createElement(NewPaneDialog, { value: newPanePrompt, onChange: setNewPanePrompt, onSubmit: (value) => {
|
|
@@ -1084,6 +1295,8 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
1084
1295
|
showCommandPrompt && (React.createElement(CommandPromptDialog, { type: showCommandPrompt, value: commandInput, onChange: setCommandInput })),
|
|
1085
1296
|
showFileCopyPrompt && (React.createElement(FileCopyPrompt, null)),
|
|
1086
1297
|
showKebabMenu && kebabMenuPaneIndex !== null && panes[kebabMenuPaneIndex] && (React.createElement(KebabMenu, { selectedOption: kebabMenuOption, actions: kebabMenuActions, paneName: panes[kebabMenuPaneIndex].slug })),
|
|
1298
|
+
showSettingsDialog && (React.createElement(SettingsDialog, { settings: settingsManager.getSettings(), globalSettings: settingsManager.getGlobalSettings(), projectSettings: settingsManager.getProjectSettings(), settingDefinitions: SETTING_DEFINITIONS, selectedIndex: settingsSelectedIndex, mode: settingsMode, editingKey: settingsEditingKey, editingValueIndex: settingsEditingValueIndex, scopeIndex: settingsScopeIndex })),
|
|
1299
|
+
showHooksDialog && (React.createElement(HooksDialog, { hooks: hooksData, selectedIndex: hooksSelectedIndex })),
|
|
1087
1300
|
actionSystem.actionState.showConfirmDialog && (React.createElement(ActionConfirmDialog, { key: "confirm-dialog", title: actionSystem.actionState.confirmTitle, message: actionSystem.actionState.confirmMessage, yesLabel: actionSystem.actionState.confirmYesLabel, noLabel: actionSystem.actionState.confirmNoLabel, selectedIndex: actionSystem.actionState.confirmSelectedIndex })),
|
|
1088
1301
|
actionSystem.actionState.showChoiceDialog && (React.createElement(ActionChoiceDialog, { key: "choice-dialog", title: actionSystem.actionState.choiceTitle, message: actionSystem.actionState.choiceMessage, options: actionSystem.actionState.choiceOptions, selectedIndex: actionSystem.actionState.choiceSelectedIndex })),
|
|
1089
1302
|
actionSystem.actionState.showInputDialog && (React.createElement(ActionInputDialog, { key: "input-dialog", title: actionSystem.actionState.inputTitle, message: actionSystem.actionState.inputMessage, placeholder: actionSystem.actionState.inputPlaceholder, value: actionSystem.actionState.inputValue, onValueChange: (value) => {
|
|
@@ -1111,11 +1324,17 @@ const DmuxApp = ({ panesFile, projectName, sessionName, settingsFile, autoUpdate
|
|
|
1111
1324
|
return `Grid: ${cols} cols × ${rows} rows | Selected: row ${pos.row}, col ${pos.col} | Terminal: ${terminalWidth}w`;
|
|
1112
1325
|
})() }),
|
|
1113
1326
|
React.createElement(Text, { dimColor: true },
|
|
1327
|
+
updateAvailable && updateInfo && (React.createElement(Text, { color: "red", bold: true }, "Update available: npm i -g dmux@latest ")),
|
|
1114
1328
|
"v",
|
|
1115
1329
|
packageJson.version,
|
|
1116
|
-
|
|
1117
|
-
" \u2022
|
|
1118
|
-
|
|
1330
|
+
serverPort && serverPort > 0 && (React.createElement(Text, { dimColor: true },
|
|
1331
|
+
" \u2022 ",
|
|
1332
|
+
React.createElement(Text, { color: "cyan" },
|
|
1333
|
+
"http://127.0.0.1:",
|
|
1334
|
+
serverPort))),
|
|
1335
|
+
debugMessage && (React.createElement(Text, { dimColor: true },
|
|
1336
|
+
" \u2022 ",
|
|
1337
|
+
debugMessage)))));
|
|
1119
1338
|
};
|
|
1120
1339
|
export default DmuxApp;
|
|
1121
1340
|
//# sourceMappingURL=DmuxApp.js.map
|